ZMediumToMarkdown 1.9.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acc5589c92b8dd859f91b98fe7c2f1073a39af102ee8ebce27f1351824ffcab7
4
- data.tar.gz: b14f257296741edd700bf484c37da6b2e386ddfb96dffca540b60cea8c04fecc
3
+ metadata.gz: 796d995f3d5f3f1edf3de599a28df4a8bea5ab9083d9bf8191d0d0535c924eb3
4
+ data.tar.gz: 7fa92c888507d4fea9293a3649c1656d3891a04b34d73d035d1a65676a5c8dc4
5
5
  SHA512:
6
- metadata.gz: da41323a9b967724f758535d4ad8bb191cc1c015929b8af49e94851c7ff83b8a45d0ee8eb25298e2712b4acfbe1d3263cf4d327609cfc9f170e16cffadd347a9
7
- data.tar.gz: c8a491d922669dd8ac947e658367fcbc093a007bda351ed9f7627213ad635c0d4246d36d09862ae597312147d4627f0314f12547df2c37d95a8bc400064c0897
6
+ metadata.gz: 434c7f737e281189a0feaa821d25e936632be3e72731a495ba62ea945bfef67063518637879b44ecf5f9121ce4ae8b302553bca55959a93e874904cc0fddc808
7
+ data.tar.gz: 298efd510208b800826cd39be456e47a7b1744291078fd7e61b954a59e9c9257e796c09ed1813b098ad0c8615c17b1b7e19217388dcbcd9f085d9b5151a35663
data/lib/Helper.rb CHANGED
@@ -98,21 +98,31 @@ class Helper
98
98
  end
99
99
  end
100
100
 
101
- def self.createPostInfo(postInfo)
102
-
103
- title = postInfo.title.gsub("[","")
104
- title = title.gsub("]","")
101
+ def self.createPostInfo(postInfo, isForJekyll)
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
117
+ result += "render_with_liquid: false\n"
105
118
 
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 += "---\n"
113
- result += "\r\n"
119
+ result += "---\n"
120
+ result += "\r\n"
114
121
 
115
- result
122
+ result
123
+ else
124
+ nil
125
+ end
116
126
  end
117
127
 
118
128
  def self.printNewVersionMessageIfExists()
@@ -183,15 +193,9 @@ class Helper
183
193
 
184
194
  def self.createWatermark(postURL)
185
195
  text = "\r\n\r\n\r\n"
186
- text += "+-----------------------------------------------------------------------------------+"
187
- text += "\r\n"
196
+ text += "_Converted [Medium Post](#{postURL}) by [ZMediumToMarkdown](https://github.com/ZhgChgLi/ZMediumToMarkdown)._"
188
197
  text += "\r\n"
189
- text += "| **[View original post on Medium](#{postURL}) - Converted by [ZhgChgLi](https://zhgchg.li)/[ZMediumToMarkdown](https://github.com/ZhgChgLi/ZMediumToMarkdown)** |"
190
- text += "\r\n"
191
- text += "\r\n"
192
- text += "+-----------------------------------------------------------------------------------+"
193
- text += "\r\n"
194
-
198
+
195
199
  text
196
200
  end
197
201
  end
@@ -25,15 +25,9 @@ class CodeBlockParser < Parser
25
25
  def parse(paragraph)
26
26
  if CodeBlockParser.isCodeBlock(paragraph)
27
27
  result = "```\n"
28
- if isForJekyll
29
- result += "{% raw %}\n"
30
- end
31
28
 
32
- result += paragraph.text
29
+ result += paragraph.text.chomp
33
30
 
34
- if isForJekyll
35
- result += "\n{% endraw %}"
36
- end
37
31
  result += "\n```"
38
32
  else
39
33
  if !nextParser.nil?
@@ -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/#{paragraph.metadata.id}"
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)
@@ -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"
@@ -76,15 +77,9 @@ class IframeParser < Parser
76
77
  gistRAW = Request.body(Request.URL(a['href']))
77
78
 
78
79
  result = "```#{lang}\n"
79
- if isForJekyll
80
- result += "{% raw %}\n"
81
- end
82
80
 
83
- result += gistRAW
81
+ result += gistRAW.chomp
84
82
 
85
- if isForJekyll
86
- result += "\n{% endraw %}"
87
- end
88
83
  result += "\n```"
89
84
  end
90
85
  end
@@ -96,17 +91,51 @@ class IframeParser < Parser
96
91
  ogURL = params["url"]
97
92
  end
98
93
  end
99
- ogImageURL = Helper.fetchOGImage(ogURL)
100
94
 
101
- title = paragraph.iframe.title
102
- if title.nil? or title == ""
103
- title = Helper.escapeMarkdown(ogURL)
104
- end
105
-
106
- if !ogImageURL.nil?
107
- result = "\r\n\r\n[![#{title}](#{ogImageURL} \"#{title}\")](#{ogURL})\r\n\r\n"
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
108
126
  else
109
- result = "[#{title}](#{ogURL})"
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
110
139
  end
111
140
  end
112
141
  end
@@ -21,17 +21,12 @@ class PREParser < Parser
21
21
  def parse(paragraph)
22
22
  if PREParser.isPRE(paragraph)
23
23
  result = "```\n"
24
- if isForJekyll
25
- result += "{% raw %}\n"
26
- end
27
24
 
28
25
  paragraph.text.each_line do |p|
29
26
  result += p
30
27
  end
31
28
 
32
- if isForJekyll
33
- result += "\n{% endraw %}"
34
- end
29
+ result = result.chomp
35
30
  result += "\n```"
36
31
 
37
32
  result
data/lib/Post.rb CHANGED
@@ -6,10 +6,12 @@ require 'nokogiri'
6
6
  require 'json'
7
7
  require 'date'
8
8
 
9
- class Post
9
+ require 'ImageDownloader'
10
+ require 'PathPolicy'
10
11
 
12
+ class Post
11
13
  class PostInfo
12
- attr_accessor :title, :tags, :creator, :firstPublishedAt, :latestPublishedAt, :collectionName
14
+ attr_accessor :title, :tags, :creator, :firstPublishedAt, :latestPublishedAt, :collectionName, :description, :previewImage
13
15
  end
14
16
 
15
17
  def self.getPostIDFromPostURLString(postURLString)
@@ -58,11 +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()
65
+ postInfo.description = content&.dig("Post:#{postID}", "previewContent", "subtitle")
63
66
  postInfo.title = content&.dig("Post:#{postID}", "title")
64
67
  postInfo.tags = content&.dig("Post:#{postID}", "tags").map{ |tag| tag["__ref"].gsub! 'Tag:', '' }
65
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
+
66
84
  creatorRef = content&.dig("Post:#{postID}", "creator", "__ref")
67
85
  if !creatorRef.nil?
68
86
  postInfo.creator = content&.dig(creatorRef, "name")
@@ -50,9 +50,9 @@ class ZMediumFetcher
50
50
  info += "-"
51
51
  end
52
52
  if !currentPostParagraphIndex.nil? && !totalPostParagraphsLength.nil?
53
- info += "[#{postPath[0..10]}...(#{currentPostParagraphIndex}/#{totalPostParagraphsLength})]"
53
+ info += "[#{postPath[0..15]}...(#{currentPostParagraphIndex}/#{totalPostParagraphsLength})]"
54
54
  else
55
- info += "[#{postPath[0..10]}...]"
55
+ info += "[#{postPath[0..15]}...]"
56
56
  end
57
57
  end
58
58
 
@@ -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
 
@@ -230,7 +230,7 @@ class ZMediumFetcher
230
230
  absolutePath = postPathPolicy.getAbsolutePath("#{postWithDatePath}.md")
231
231
 
232
232
  # if markdown file is exists and last modification time is >= latestPublishedAt(last update post time on medium)
233
- if File.file?(absolutePath) && File.mtime(absolutePath) >= postInfo.latestPublishedAt
233
+ if File.file?(absolutePath) && File.mtime(absolutePath).to_time.to_i >= postInfo.latestPublishedAt.to_i
234
234
  # Already downloaded and nothing has changed!, Skip!
235
235
  progress.currentPostParagraphIndex = paragraphs.length
236
236
  progress.message = "Skip, Post already downloaded and nothing has changed!"
@@ -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
- file.puts(Helper.createPostInfo(postInfo))
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
- file.puts(Helper.createWatermark(postURL))
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
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ZMediumToMarkdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.6
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ZhgChgLi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-15 00:00:00.000000000 Z
11
+ date: 2022-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri