ZMediumToMarkdown 1.9.8 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/Helper.rb +25 -28
- data/lib/Parsers/IMGParser.rb +1 -1
- data/lib/Parsers/IframeParser.rb +44 -9
- data/lib/Post.rb +20 -3
- data/lib/ZMediumFetcher.rb +17 -11
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 796d995f3d5f3f1edf3de599a28df4a8bea5ab9083d9bf8191d0d0535c924eb3
|
4
|
+
data.tar.gz: 7fa92c888507d4fea9293a3649c1656d3891a04b34d73d035d1a65676a5c8dc4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 434c7f737e281189a0feaa821d25e936632be3e72731a495ba62ea945bfef67063518637879b44ecf5f9121ce4ae8b302553bca55959a93e874904cc0fddc808
|
7
|
+
data.tar.gz: 298efd510208b800826cd39be456e47a7b1744291078fd7e61b954a59e9c9257e796c09ed1813b098ad0c8615c17b1b7e19217388dcbcd9f085d9b5151a35663
|
data/lib/Helper.rb
CHANGED
@@ -99,24 +99,30 @@ class Helper
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def self.createPostInfo(postInfo, isForJekyll)
|
102
|
-
|
103
|
-
title = postInfo.title.gsub("[","")
|
104
|
-
title = title.gsub("]","")
|
105
|
-
|
106
|
-
result = "---\n"
|
107
|
-
result += "title: #{title}\n"
|
108
|
-
result += "author: #{postInfo.creator}\n"
|
109
|
-
result += "date: #{postInfo.firstPublishedAt.strftime('%Y-%m-%dT%H:%M:%S.%LZ')}\n"
|
110
|
-
result += "categories: #{postInfo.collectionName}\n"
|
111
|
-
result += "tags: [#{postInfo.tags.join(",")}]\n"
|
112
|
-
result += "description: #{postInfo.description}\n"
|
113
102
|
if isForJekyll
|
103
|
+
title = postInfo.title.gsub("[","")
|
104
|
+
title = title.gsub("]","")
|
105
|
+
|
106
|
+
result = "---\n"
|
107
|
+
result += "title: #{title}\n"
|
108
|
+
result += "author: #{postInfo.creator}\n"
|
109
|
+
result += "date: #{postInfo.firstPublishedAt.strftime('%Y-%m-%dT%H:%M:%S.%LZ')}\n"
|
110
|
+
result += "categories: #{postInfo.collectionName}\n"
|
111
|
+
result += "tags: [#{postInfo.tags.join(",")}]\n"
|
112
|
+
result += "description: #{postInfo.description}\n"
|
113
|
+
if !postInfo.previewImage.nil?
|
114
|
+
result += "image:\r\n"
|
115
|
+
result += " path: #{postInfo.previewImage}\r\n"
|
116
|
+
end
|
114
117
|
result += "render_with_liquid: false\n"
|
115
|
-
end
|
116
|
-
result += "---\n"
|
117
|
-
result += "\r\n"
|
118
118
|
|
119
|
-
|
119
|
+
result += "---\n"
|
120
|
+
result += "\r\n"
|
121
|
+
|
122
|
+
result
|
123
|
+
else
|
124
|
+
nil
|
125
|
+
end
|
120
126
|
end
|
121
127
|
|
122
128
|
def self.printNewVersionMessageIfExists()
|
@@ -186,19 +192,10 @@ class Helper
|
|
186
192
|
|
187
193
|
|
188
194
|
def self.createWatermark(postURL)
|
189
|
-
text = ""
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
# text += "\r\n"
|
194
|
-
# text += "\r\n"
|
195
|
-
# text += "| **[View original post on Medium](#{postURL}) - Converted by [ZhgChgLi](https://zhgchg.li)/[ZMediumToMarkdown](https://github.com/ZhgChgLi/ZMediumToMarkdown)** |"
|
196
|
-
# text += "\r\n"
|
197
|
-
# text += "\r\n"
|
198
|
-
# text += "+-----------------------------------------------------------------------------------+"
|
199
|
-
# text += "\r\n"
|
200
|
-
|
201
|
-
# no need to show any watermark :)
|
195
|
+
text = "\r\n\r\n\r\n"
|
196
|
+
text += "_Converted [Medium Post](#{postURL}) by [ZMediumToMarkdown](https://github.com/ZhgChgLi/ZMediumToMarkdown)._"
|
197
|
+
text += "\r\n"
|
198
|
+
|
202
199
|
text
|
203
200
|
end
|
204
201
|
end
|
data/lib/Parsers/IMGParser.rb
CHANGED
@@ -18,7 +18,7 @@ class IMGParser < Parser
|
|
18
18
|
|
19
19
|
fileName = paragraph.metadata.id #d*fsafwfe.jpg
|
20
20
|
|
21
|
-
imageURL = "https://miro.medium.com/max/1400/#{
|
21
|
+
imageURL = "https://miro.medium.com/max/1400/#{fileName}"
|
22
22
|
|
23
23
|
imagePathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), paragraph.postID)
|
24
24
|
absolutePath = imagePathPolicy.getAbsolutePath(fileName)
|
data/lib/Parsers/IframeParser.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
$lib = File.expand_path('../', File.dirname(__FILE__))
|
2
2
|
|
3
3
|
require 'uri'
|
4
|
+
require 'net/http'
|
4
5
|
|
5
6
|
require "Request"
|
6
7
|
require "Parsers/Parser"
|
@@ -90,17 +91,51 @@ class IframeParser < Parser
|
|
90
91
|
ogURL = params["url"]
|
91
92
|
end
|
92
93
|
end
|
93
|
-
ogImageURL = Helper.fetchOGImage(ogURL)
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
95
|
+
twitterID = ogURL[/^(https\:\/\/twitter\.com\/){1}.+(\/){1}(\d+)/, 3]
|
96
|
+
|
97
|
+
if !twitterID.nil?
|
98
|
+
uri = URI("https://api.twitter.com/1.1/statuses/show.json?simple_quoted_tweet=true&include_entities=true&tweet_mode=extended&include_cards=1&id=#{twitterID}")
|
99
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
100
|
+
https.use_ssl = true
|
101
|
+
|
102
|
+
request = Net::HTTP::Get.new(uri)
|
103
|
+
request['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.17.375.766 Safari/537.36';
|
104
|
+
request['Authorization'] = 'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA'; # twitter private api
|
105
|
+
|
106
|
+
response = https.request(request)
|
107
|
+
if response.code.to_i == 200
|
108
|
+
twitterObj = JSON.parse(response.read_body)
|
109
|
+
|
110
|
+
fullText = twitterObj["full_text"]
|
111
|
+
twitterObj["entities"]["user_mentions"].each do |user_mention|
|
112
|
+
fullText = fullText.gsub(user_mention["screen_name"],"[#{user_mention["screen_name"]}](https://twitter.com/#{user_mention["screen_name"]})")
|
113
|
+
end
|
114
|
+
twitterObj["entities"]["urls"].each do |url|
|
115
|
+
fullText = fullText.gsub(url["url"],"[#{url["display_url"]}](#{url["expanded_url"]})")
|
116
|
+
end
|
117
|
+
|
118
|
+
createdAt = Time.parse(twitterObj["created_at"]).strftime('%Y-%m-%d %H:%M:%S')
|
119
|
+
result = "\n\n"
|
120
|
+
result += "■■■■■■■■■■■■■■ \n"
|
121
|
+
result += "> **[#{twitterObj["user"]["name"]}](https://twitter.com/#{twitterObj["user"]["screen_name"]}) @ Twitter Says:** \n\n"
|
122
|
+
result += "> > #{fullText} \n\n"
|
123
|
+
result += "> **Tweeted at [#{createdAt}](#{ogURL}).** \n\n"
|
124
|
+
result += "■■■■■■■■■■■■■■ \n\n"
|
125
|
+
end
|
102
126
|
else
|
103
|
-
|
127
|
+
ogImageURL = Helper.fetchOGImage(ogURL)
|
128
|
+
|
129
|
+
title = paragraph.iframe.title
|
130
|
+
if title.nil? or title == ""
|
131
|
+
title = Helper.escapeMarkdown(ogURL)
|
132
|
+
end
|
133
|
+
|
134
|
+
if !ogImageURL.nil?
|
135
|
+
result = "\r\n\r\n[![#{title}](#{ogImageURL} \"#{title}\")](#{ogURL})\r\n\r\n"
|
136
|
+
else
|
137
|
+
result = "[#{title}](#{ogURL})"
|
138
|
+
end
|
104
139
|
end
|
105
140
|
end
|
106
141
|
end
|
data/lib/Post.rb
CHANGED
@@ -6,10 +6,12 @@ require 'nokogiri'
|
|
6
6
|
require 'json'
|
7
7
|
require 'date'
|
8
8
|
|
9
|
-
|
9
|
+
require 'ImageDownloader'
|
10
|
+
require 'PathPolicy'
|
10
11
|
|
12
|
+
class Post
|
11
13
|
class PostInfo
|
12
|
-
attr_accessor :title, :tags, :creator, :firstPublishedAt, :latestPublishedAt, :collectionName, :description
|
14
|
+
attr_accessor :title, :tags, :creator, :firstPublishedAt, :latestPublishedAt, :collectionName, :description, :previewImage
|
13
15
|
end
|
14
16
|
|
15
17
|
def self.getPostIDFromPostURLString(postURLString)
|
@@ -58,12 +60,27 @@ class Post
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
def self.parsePostInfoFromPostContent(content, postID)
|
63
|
+
def self.parsePostInfoFromPostContent(content, postID, pathPolicy)
|
62
64
|
postInfo = PostInfo.new()
|
63
65
|
postInfo.description = content&.dig("Post:#{postID}", "previewContent", "subtitle")
|
64
66
|
postInfo.title = content&.dig("Post:#{postID}", "title")
|
65
67
|
postInfo.tags = content&.dig("Post:#{postID}", "tags").map{ |tag| tag["__ref"].gsub! 'Tag:', '' }
|
66
68
|
|
69
|
+
previewImage = content&.dig("Post:#{postID}", "previewImage", "__ref")
|
70
|
+
if !previewImage.nil?
|
71
|
+
previewImageFIleName = content&.dig(previewImage, "id")
|
72
|
+
|
73
|
+
imagePathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), postID)
|
74
|
+
absolutePath = imagePathPolicy.getAbsolutePath(previewImageFIleName)
|
75
|
+
|
76
|
+
imageURL = "https://miro.medium.com/max/1400/#{previewImageFIleName}"
|
77
|
+
|
78
|
+
if ImageDownloader.download(absolutePath, imageURL)
|
79
|
+
relativePath = "#{pathPolicy.getRelativePath(nil)}/#{imagePathPolicy.getRelativePath(previewImageFIleName)}"
|
80
|
+
postInfo.previewImage = relativePath
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
67
84
|
creatorRef = content&.dig("Post:#{postID}", "creator", "__ref")
|
68
85
|
if !creatorRef.nil?
|
69
86
|
postInfo.creator = content&.dig(creatorRef, "name")
|
data/lib/ZMediumFetcher.rb
CHANGED
@@ -121,6 +121,14 @@ class ZMediumFetcher
|
|
121
121
|
postPath = Post.getPostPathFromPostURLString(postURL)
|
122
122
|
end
|
123
123
|
|
124
|
+
if isForJekyll
|
125
|
+
postPathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), "_posts/zmediumtomarkdown")
|
126
|
+
imagePathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), "assets")
|
127
|
+
else
|
128
|
+
postPathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), "zmediumtomarkdown")
|
129
|
+
imagePathPolicy = PathPolicy.new(postPathPolicy.getAbsolutePath(nil), "assets")
|
130
|
+
end
|
131
|
+
|
124
132
|
progress.postPath = postPath
|
125
133
|
progress.message = "Downloading Post..."
|
126
134
|
progress.printLog()
|
@@ -132,7 +140,7 @@ class ZMediumFetcher
|
|
132
140
|
raise "Error: Content is empty! PostURL: #{postURL}"
|
133
141
|
end
|
134
142
|
|
135
|
-
postInfo = Post.parsePostInfoFromPostContent(postContent, postID)
|
143
|
+
postInfo = Post.parsePostInfoFromPostContent(postContent, postID, imagePathPolicy)
|
136
144
|
|
137
145
|
sourceParagraphs = Post.fetchPostParagraphs(postID)
|
138
146
|
if sourceParagraphs.nil?
|
@@ -207,14 +215,6 @@ class ZMediumFetcher
|
|
207
215
|
paragraphs.append(paragraph)
|
208
216
|
previousParagraph = paragraph
|
209
217
|
end
|
210
|
-
|
211
|
-
if isForJekyll
|
212
|
-
postPathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), "_posts/zmediumtomarkdown")
|
213
|
-
imagePathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), "assets")
|
214
|
-
else
|
215
|
-
postPathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(nil), "zmediumtomarkdown")
|
216
|
-
imagePathPolicy = PathPolicy.new(postPathPolicy.getAbsolutePath(nil), "assets")
|
217
|
-
end
|
218
218
|
|
219
219
|
startParser = buildParser(imagePathPolicy)
|
220
220
|
|
@@ -239,7 +239,10 @@ class ZMediumFetcher
|
|
239
239
|
Helper.createDirIfNotExist(postPathPolicy.getAbsolutePath(nil))
|
240
240
|
File.open(absolutePath, "w+") do |file|
|
241
241
|
# write postInfo into top
|
242
|
-
|
242
|
+
postMetaInfo = Helper.createPostInfo(postInfo, isForJekyll)
|
243
|
+
if !postMetaInfo.nil?
|
244
|
+
file.puts(postMetaInfo)
|
245
|
+
end
|
243
246
|
|
244
247
|
index = 0
|
245
248
|
paragraphs.each do |paragraph|
|
@@ -260,7 +263,10 @@ class ZMediumFetcher
|
|
260
263
|
progress.printLog()
|
261
264
|
end
|
262
265
|
|
263
|
-
|
266
|
+
postWatermark = Helper.createWatermark(postURL)
|
267
|
+
if !postWatermark.nil?
|
268
|
+
file.puts(postWatermark)
|
269
|
+
end
|
264
270
|
end
|
265
271
|
FileUtils.touch absolutePath, :mtime => postInfo.latestPublishedAt
|
266
272
|
|