jekyll-crosseverything-to-medium 0.0.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/lib/jekyll-crosseverything-to-medium.rb +220 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cf717970cd9398b00938e7e185767d9dbd298e16
|
4
|
+
data.tar.gz: 4effb5a9330c68a0767d5291a5e7d7315565b953
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 90be13033347102b620c794599c94c803fca8a31ed90b5238a2ac60bf53deabfeffc1ff7428960e5ca4d444c48a71dca26f815e31338bade55e2889d29eb22aa
|
7
|
+
data.tar.gz: 7d5b3b57da2301df1a3b246a93cd72a96cb7e36cde7fca0c849e76b7e1ee31203af3ca4fdf30d65cdb204c94a4dfc7b2050bdd88c69146014ded04d73f815e51
|
@@ -0,0 +1,220 @@
|
|
1
|
+
# By Vincenzo Tilotta (tailot@gmail.com), based on the work of Jeremy Keith and Aaron Gustafson
|
2
|
+
# https://github.com/tailot/jekyll-crosserything-to-medium
|
3
|
+
# https://github.com/aarongustafson/jekyll-crosseverything_to_medium
|
4
|
+
# https://gist.github.com/adactio/c174a4a68498e30babfd
|
5
|
+
# Licence : MIT
|
6
|
+
#
|
7
|
+
# This generator cross-posts entries to Medium. To work, this script requires
|
8
|
+
# a MEDIUM_USER_ID environment variable and a MEDIUM_INTEGRATION_TOKEN.
|
9
|
+
#
|
10
|
+
# The generator will only pick up posts with the following front matter:
|
11
|
+
#
|
12
|
+
# `crosseverything_to_medium: true`
|
13
|
+
#
|
14
|
+
# You can control crosseverythinging globally by setting `enabled: true` under the
|
15
|
+
# `jekyll-crosseverything_to_medium` variable in your Jekyll configuration file.
|
16
|
+
# Setting it to false will skip the processing loop entirely which can be
|
17
|
+
# useful for local preview builds.
|
18
|
+
|
19
|
+
require 'json'
|
20
|
+
require 'net/http'
|
21
|
+
require 'net/https'
|
22
|
+
require 'kramdown'
|
23
|
+
require 'uri'
|
24
|
+
require 'date'
|
25
|
+
|
26
|
+
module Jekyll
|
27
|
+
class MediumCrosseverythingGenerator < Generator
|
28
|
+
safe true
|
29
|
+
priority :low
|
30
|
+
|
31
|
+
def generate(site)
|
32
|
+
@site = site
|
33
|
+
|
34
|
+
@settings = @site.config['jekyll-crosseverything_to_medium'] || {}
|
35
|
+
|
36
|
+
globally_enabled = if @settings.has_key?('enabled') then @settings['enabled'] else true end
|
37
|
+
cache_dir = @settings['cache'] || @site.config['source'] + '/.jekyll-crosseverything_to_medium'
|
38
|
+
backdate = if @settings.has_key? 'backdate' then @settings['backdate'] else true end
|
39
|
+
@crosseverything_file = File.join(cache_dir, "medium_crosseverything.yml")
|
40
|
+
|
41
|
+
if globally_enabled
|
42
|
+
# puts "Cross-posting enabled"
|
43
|
+
user_id = ENV['MEDIUM_USER_ID'] or false
|
44
|
+
token = ENV['MEDIUM_INTEGRATION_TOKEN'] or false
|
45
|
+
entity = ENV['MEDIUM_ENTITY'] or false
|
46
|
+
|
47
|
+
if ! user_id or ! token or ! entity
|
48
|
+
raise ArgumentError, "MediumCrosseverythingGenerator: Environment variables not found"
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
if defined?(cache_dir)
|
53
|
+
FileUtils.mkdir_p(cache_dir)
|
54
|
+
|
55
|
+
if File.exists?(@crosseverything_file)
|
56
|
+
crossposteverything = open(@crosseverything_file) { |f| YAML.load(f) }
|
57
|
+
# convert from an array to a hash (upgrading older versions of this plugin)
|
58
|
+
if crossposteverything.kind_of?(Array)
|
59
|
+
new_crosseverything = {}
|
60
|
+
crossposteverything.each do |url|
|
61
|
+
new_crosseverything[url] = 'unknown'
|
62
|
+
end
|
63
|
+
crossposteverything = new_crosseverything
|
64
|
+
end
|
65
|
+
# end upgrade
|
66
|
+
else
|
67
|
+
crossposteverything = {}
|
68
|
+
end
|
69
|
+
|
70
|
+
# If Jekyll 3.0, use hooks
|
71
|
+
if (Jekyll.const_defined? :Hooks)
|
72
|
+
Jekyll::Hooks.register entity.to_sym, :post_render do |post|
|
73
|
+
if ! post.published?
|
74
|
+
next
|
75
|
+
end
|
76
|
+
|
77
|
+
crosseverything = post.data.include? 'crosseverything_to_medium'
|
78
|
+
if ! crosseverything or ! post.data['crosseverything_to_medium']
|
79
|
+
next
|
80
|
+
end
|
81
|
+
|
82
|
+
content = post.content
|
83
|
+
url = "#{@site.config['url']}#{post.url}"
|
84
|
+
title = post.data['title']
|
85
|
+
|
86
|
+
published_at = backdate ? post.date : DateTime.now
|
87
|
+
|
88
|
+
crosseverything_payload(crossposteverything, post, content, title, url, published_at)
|
89
|
+
end
|
90
|
+
else
|
91
|
+
|
92
|
+
# post Jekyll commit 0c0aea3
|
93
|
+
# https://github.com/jekyll/jekyll/commit/0c0aea3ad7d2605325d420a23d21729c5cf7cf88
|
94
|
+
if defined? site.find_converter_instance
|
95
|
+
markdown_converter = @site.find_converter_instance(Jekyll::Converters::Markdown)
|
96
|
+
# Prior to Jekyll commit 0c0aea3
|
97
|
+
else
|
98
|
+
markdown_converter = @site.getConverterImpl(Jekyll::Converters::Markdown)
|
99
|
+
end
|
100
|
+
|
101
|
+
@site.site_payload['site'][entity].each do |post|
|
102
|
+
|
103
|
+
if ! post.published?
|
104
|
+
next
|
105
|
+
end
|
106
|
+
|
107
|
+
crosseverything = post.data.include? 'crosseverything_to_medium'
|
108
|
+
if ! crosseverything or ! post.data['crosseverything_to_medium']
|
109
|
+
next
|
110
|
+
end
|
111
|
+
|
112
|
+
# Convert the content
|
113
|
+
content = markdown_converter.convert(post.content)
|
114
|
+
# Render any plugins
|
115
|
+
content = (Liquid::Template.parse content).render @site.site_payload
|
116
|
+
|
117
|
+
url = "#{@site.config['url']}#{post.url}"
|
118
|
+
title = post.title
|
119
|
+
|
120
|
+
published_at = backdate ? post.date : DateTime.now
|
121
|
+
|
122
|
+
crosseverything_payload(crosseverything, post, content, title, url, published_at)
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def crosseverything_payload(crosseverything, post, content, title, url, published_at)
|
132
|
+
# Update any absolute URLs
|
133
|
+
# But don’t clobber protocol-less (i.e. "//") URLs
|
134
|
+
content = content.gsub /href=(["'])\/(?!\/)/, "href=\\1#{@site.config['url']}/"
|
135
|
+
content = content.gsub /src=(["'])\/(?!\/)/, "src=\\1#{@site.config['url']}/"
|
136
|
+
# puts content
|
137
|
+
|
138
|
+
# Save canonical URL
|
139
|
+
canonical_url = url
|
140
|
+
|
141
|
+
# Prepend the title and add a link back to originating site
|
142
|
+
content.prepend("<h1>#{title}</h1>")
|
143
|
+
# Append a canonical link and text
|
144
|
+
# TODO Accept a position option, e.g., top, bottom.
|
145
|
+
#
|
146
|
+
# User the user's config if it exists
|
147
|
+
if @settings['text']
|
148
|
+
canonical_text = "#{@settings['text']}"
|
149
|
+
canonical_text = canonical_text.gsub /{{ url }}/, canonical_url
|
150
|
+
# Otherwise, use boilerplate
|
151
|
+
else
|
152
|
+
canonical_text = "<p><i>This article was originally posted <a href=\"#{url}\" rel=\"canonical\">on my own site</a>.</i></p>"
|
153
|
+
end
|
154
|
+
content << canonical_text
|
155
|
+
|
156
|
+
# Strip domain name from the URL we check against
|
157
|
+
url = url.sub(/^#{@site.config['url']}?/,'')
|
158
|
+
|
159
|
+
# coerce tage to an array
|
160
|
+
tags = post.data['tags']
|
161
|
+
if tags.kind_of? String
|
162
|
+
tags = tags.split(',')
|
163
|
+
end
|
164
|
+
|
165
|
+
# Only cross-post if content has not already been cross-posted
|
166
|
+
if url and ! crosseverything.has_key? url
|
167
|
+
payload = {
|
168
|
+
'title' => title,
|
169
|
+
'contentFormat' => "html",
|
170
|
+
'content' => content,
|
171
|
+
'tags' => tags,
|
172
|
+
'publishStatus' => @settings['status'] || "public",
|
173
|
+
'publishedAt' => published_at.iso8601,
|
174
|
+
'license' => @settings['license'] || "all-rights-reserved",
|
175
|
+
'canonicalUrl' => canonical_url
|
176
|
+
}
|
177
|
+
|
178
|
+
if medium_url = crosseverything_to_medium(payload)
|
179
|
+
crosseverything[url] = medium_url
|
180
|
+
# Update cache
|
181
|
+
File.open(@crosseverything_file, 'w') { |f| YAML.dump(crosseverything, f) }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
def crosseverything_to_medium(payload)
|
188
|
+
user_id = ENV['MEDIUM_USER_ID'] or false
|
189
|
+
token = ENV['MEDIUM_INTEGRATION_TOKEN'] or false
|
190
|
+
medium_api = URI.parse("https://api.medium.com/v1/users/#{user_id}/posts")
|
191
|
+
|
192
|
+
# Build the connection
|
193
|
+
https = Net::HTTP.new(medium_api.host, medium_api.port)
|
194
|
+
https.use_ssl = true
|
195
|
+
request = Net::HTTP::Post.new(medium_api.path)
|
196
|
+
|
197
|
+
# Set the headers
|
198
|
+
request['Authorization'] = "Bearer #{token}"
|
199
|
+
request['Content-Type'] = "application/json"
|
200
|
+
request['Accept'] = "application/json"
|
201
|
+
request['Accept-Charset'] = "utf-8"
|
202
|
+
|
203
|
+
# Set the payload
|
204
|
+
request.body = JSON.generate(payload)
|
205
|
+
|
206
|
+
# Post it
|
207
|
+
response = https.request(request)
|
208
|
+
|
209
|
+
if response.code == '201'
|
210
|
+
medium_response = JSON.parse(response.body)
|
211
|
+
puts "Posted '#{payload['title']}' to Medium as #{payload['publishStatus']} (#{medium_response['data']['url']})"
|
212
|
+
return medium_response['data']['url']
|
213
|
+
else
|
214
|
+
puts "Attempted to post '#{payload['title']}' to Medium. They responded #{response.body}"
|
215
|
+
return false
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-crosseverything-to-medium
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vincenzo Tilotta
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-10 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: " This generator cross-everything entries to Medium. To work, this script
|
14
|
+
requires\n a MEDIUM_USER_ID environment variable and a MEDIUM_INTEGRATION_TOKEN,
|
15
|
+
MEDIUM_ENTITY.\n\n The generator will only pick up posts with the following front
|
16
|
+
matter:\n\n `crosseverything_to_medium: true`\n\n You can control crosseverything
|
17
|
+
globally by setting `enabled: true` under the \n `jekyll-crosserything_to_medium`
|
18
|
+
variable in your Jekyll configuration file.\n Setting it to false will skip the
|
19
|
+
processing loop entirely which can be\n useful for local preview builds.\n"
|
20
|
+
email: tailot@gmail.com
|
21
|
+
executables: []
|
22
|
+
extensions: []
|
23
|
+
extra_rdoc_files: []
|
24
|
+
files:
|
25
|
+
- lib/jekyll-crosseverything-to-medium.rb
|
26
|
+
homepage: http://rubygems.org/gems/jekyll-crosseverything-to-medium
|
27
|
+
licenses:
|
28
|
+
- MIT
|
29
|
+
metadata: {}
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 2.5.1
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: Crosseverything to Medium Generator for Jekyll
|
50
|
+
test_files: []
|