ZMediumToMarkdown 1.0.2 → 1.2.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: a2243519ed0bc3c844758752f194791e882eb88371e91c082cb6e342c5fb94c0
4
- data.tar.gz: 32fd50f1f531288f8d0e0f13a01e0412bd7acd3341f2b4e9af059635a0478f14
3
+ metadata.gz: 837c899a0d017fa83febc0f96e84a89527a517754cbee44f6e91320c7b2cd292
4
+ data.tar.gz: cb5c49e7a67f99ab888cb0797edaf4c0ce237da3e8c41bfda963395bd606b1cd
5
5
  SHA512:
6
- metadata.gz: cce4567526e3db1c0d92ef7fa5b1f2953a4242c8dc505fd35f090deee5df8eabd81762712b72ebd4a854082c3a4eae2057622f7e4283335d1df98a191235f38a
7
- data.tar.gz: c87a247402fdc62ab3634ffaa422729cfb5fdfe1f0f6220a70c5e5bb598a542f05a64b97a42c747cab7521f63d8942f179bfb74def31ccefa0d49002da60d673
6
+ metadata.gz: f9339415de8183d6c255bf28db437c61e8913c242e5ed3270d070285b1282717187511a974fdc6c0ef391c37a6308bcf3d7f866dd0fa508a7e00fc004d05ca87
7
+ data.tar.gz: 832198d0d8cf5851aedfa7f69a9193cad42f71f21f06fb29a832957140fdfd6d8e3099429b8085824eae2f19d0d05c6c2615f73d012fa16679fcf49945918862
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ $lib = File.expand_path('../lib', File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift($lib)
6
+
7
+ require "ZMediumFetcher"
8
+ require "Helper"
9
+ require "optparse"
10
+
11
+ class Main
12
+ def initialize
13
+ fetcher = ZMediumFetcher.new
14
+ ARGV << '-h' if ARGV.empty?
15
+ OptionParser.new do |opts|
16
+ opts.banner = "Usage: ZMediumFetcher [options]"
17
+
18
+ opts.on('-uUSERNAME', '--username=USERNAME', 'test') do |username|
19
+ Helper.checkNewVersion()
20
+
21
+ pathPolicy = PathPolicy.new("#{File.expand_path('../', File.dirname(__FILE__))}", "Output")
22
+ fetcher.downloadPostsByUsername(username, pathPolicy)
23
+ end
24
+
25
+ opts.on('-pPOST_URL', '--postURL=POST_URL', 'test') do |postURL|
26
+ Helper.checkNewVersion()
27
+
28
+ pathPolicy = PathPolicy.new("#{File.expand_path('../', File.dirname(__FILE__))}", "Output")
29
+ fetcher.downloadPost(postURL, pathPolicy)
30
+ end
31
+
32
+ opts.on('-n', '--new', 'Update to latest version') do |postURL|
33
+ if Helper.compareVersion(Helper.getRemoteVersionFromGithub(), Helper.getLocalVersionFromGemspec())
34
+ Helper.downloadLatestVersion()
35
+ else
36
+ puts "You're using the latest version :)"
37
+ end
38
+ end
39
+
40
+ end.parse!
41
+
42
+ Helper.logLatestRunVersion()
43
+ end
44
+ end
45
+
46
+ begin
47
+ puts "#https://github.com/ZhgChgLi/ZMediumToMarkdown"
48
+ puts "You have read and agree with the Disclaimer."
49
+ Main.new()
50
+ puts "Execute Successfully!!!"
51
+ puts "#https://github.com/ZhgChgLi/ZMediumToMarkdown"
52
+ puts "#Thanks for using this tool."
53
+ puts "#If this is helpful, please help to star the repo or recommend it to your friends."
54
+ rescue => e
55
+ puts "#Error: #{e.class} #{e.message}\n"
56
+ puts e.backtrace
57
+ puts "#Please feel free to open an Issue or submit a fix/contribution via Pull Request on:\n"
58
+ puts "#https://github.com/ZhgChgLi/ZMediumToMarkdown\n"
59
+ end
data/lib/Helper.rb CHANGED
@@ -1,8 +1,30 @@
1
1
  $lib = File.expand_path('../lib', File.dirname(__FILE__))
2
2
 
3
+ require 'fileutils'
4
+ require 'date'
5
+ require 'PathPolicy'
3
6
  require 'Post'
7
+ require "Request"
8
+ require 'json'
9
+ require 'open-uri'
10
+ require 'zip'
4
11
 
5
12
  class Helper
13
+
14
+ class Version
15
+ attr_accessor :major, :minor, :patch
16
+
17
+ def initialize(major, minor, patch)
18
+ @major = major.to_i
19
+ @minor = minor.to_i
20
+ @patch = patch.to_i
21
+ end
22
+
23
+ def to_string()
24
+ "#{major.to_s}.#{minor.to_s}.#{patch.to_s}"
25
+ end
26
+ end
27
+
6
28
  def self.createDirIfNotExist(dirPath)
7
29
  dirs = dirPath.split("/")
8
30
  currentDir = ""
@@ -23,11 +45,50 @@ class Helper
23
45
  puts "####################################################\n"
24
46
  end
25
47
 
48
+ def self.downloadLatestVersion()
49
+ apiPath = 'https://api.github.com/repos/ZhgChgLi/ZMediumToMarkdown/releases'
50
+ versions = JSON.parse(Request.URL(apiPath).body).sort { |a,b| b["id"] <=> a["id"] }
51
+
52
+ version = nil
53
+ index = 0
54
+ while version == nil do
55
+ thisVersion = versions[index]
56
+ if thisVersion["prerelease"] == false
57
+ version = thisVersion
58
+ next
59
+ end
60
+ index += 1
61
+ end
62
+
63
+ zipFilePath = version["zipball_url"]
64
+ puts "Downloading latest version from github..."
65
+ open('latest.zip', 'wb') do |fo|
66
+ fo.print open(zipFilePath).read
67
+ end
68
+
69
+ puts "Unzip..."
70
+ Zip::File.open("latest.zip") do |zipfile|
71
+ zipfile.each do |file|
72
+ fileNames = file.name.split("/")
73
+ fileNames.shift
74
+ filePath = fileNames.join("/")
75
+ if filePath != ''
76
+ puts "Unzinp...#{filePath}"
77
+ zipfile.extract(file, filePath) { true }
78
+ end
79
+ end
80
+ end
81
+ File.delete("latest.zip")
82
+
83
+ tagName = version["tag_name"]
84
+ puts "Update to version #{tagName} successfully!"
85
+ end
86
+
26
87
  def self.createPostInfo(postInfo)
27
88
  result = "---\n"
28
89
  result += "title: #{postInfo.title}\n"
29
90
  result += "author: #{postInfo.creator}\n"
30
- result += "date: #{postInfo.firstPublishedAt}\n"
91
+ result += "date: #{postInfo.firstPublishedAt.strftime('%Y-%m-%dT%H:%M:%S.%LZ')}\n"
31
92
  result += "tags: [#{postInfo.tags.join(",")}]\n"
32
93
  result += "---\n"
33
94
  result += "\r\n"
@@ -35,6 +96,89 @@ class Helper
35
96
  result
36
97
  end
37
98
 
99
+ def self.checkNewVersion()
100
+ if Helper.compareVersion(Helper.getRemoteVersionFromGithub(), Helper.getLocalVersionFromGemspec())
101
+ puts "##########################################################"
102
+ puts "##### New Version Available!!! #####"
103
+ puts "##### Please type `bin/ZMediumToMarkdown -n` to update!!##"
104
+ puts "##########################################################"
105
+ end
106
+ end
107
+
108
+ def self.getLocalVersionFromGemspec()
109
+ rootPath = File.expand_path('../', File.dirname(__FILE__))
110
+ gemspecContent = File.read("#{rootPath}/ZMediumToMarkdown.gemspec")
111
+ result = gemspecContent[/(gem\.version){1}\s+(\=)\s+(\'){1}(\d+(\.){1}\d+(\.){1}\d+){1}(\'){1}/, 4]
112
+
113
+ if !result.nil?
114
+ versions = result.split(".")
115
+ Version.new(versions[0],versions[1],versions[2])
116
+ else
117
+ nil
118
+ end
119
+ end
120
+
121
+ def self.logLatestRunVersion()
122
+ version = Helper.getLocalVersionFromGemspec()
123
+ rootPath = File.expand_path('../', File.dirname(__FILE__))
124
+
125
+ File.open("#{rootPath}/.latestRunVersion" , 'w+') do |file|
126
+ file.puts(version.to_string())
127
+ end
128
+ end
129
+
130
+ def self.getLocalVersionFromFile()
131
+ rootPath = File.expand_path('../', File.dirname(__FILE__))
132
+ result = File.read("#{rootPath}/.latestRunVersion")
133
+
134
+ if !result.nil?
135
+ versions = result.split(".")
136
+ Version.new(versions[0],versions[1],versions[2])
137
+ else
138
+ nil
139
+ end
140
+ end
141
+
142
+ def self.getRemoteVersionFromGithub()
143
+ apiPath = 'https://api.github.com/repos/ZhgChgLi/ZMediumToMarkdown/releases'
144
+ versions = JSON.parse(Request.URL(apiPath).body).sort { |a,b| b["id"] <=> a["id"] }
145
+
146
+ tagName = nil
147
+ index = 0
148
+ while tagName == nil do
149
+ thisVersion = versions[index]
150
+ if thisVersion["prerelease"] == false
151
+ tagName = thisVersion["tag_name"]
152
+ next
153
+ end
154
+ index += 1
155
+ end
156
+
157
+ if !tagName.nil?
158
+ versions = (tagName.downcase.gsub! 'v','') .split(".")
159
+ Version.new(versions[0],versions[1],versions[2])
160
+ else
161
+ nil
162
+ end
163
+ end
164
+
165
+ def self.compareVersion(version1, version2)
166
+ if version1.major > version2.major
167
+ true
168
+ else
169
+ if version1.minor > version2.minor
170
+ true
171
+ else
172
+ if version1.patch > version2.patch
173
+ true
174
+ else
175
+ false
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+
38
182
  def self.createWatermark(postURL)
39
183
  text = "\r\n\r\n\r\n"
40
184
  text += "+-----------------------------------------------------------------------------------+"
@@ -7,7 +7,11 @@ class BQParser < Parser
7
7
  attr_accessor :nextParser
8
8
  def parse(paragraph)
9
9
  if paragraph.type == 'BQ'
10
- "> #{paragraph.text}"
10
+ result = ""
11
+ paragraph.text.each_line do |p|
12
+ result += "> #{p}"
13
+ end
14
+ result
11
15
  else
12
16
  if !nextParser.nil?
13
17
  nextParser.parse(paragraph)
@@ -16,10 +16,11 @@ class PREParser < Parser
16
16
 
17
17
  def parse(paragraph)
18
18
  if PREParser.isPRE(paragraph)
19
- result = ""
19
+ result = "```\n"
20
20
  paragraph.text.each_line do |p|
21
- result += "> #{p}"
21
+ result += p
22
22
  end
23
+ result += "\n```"
23
24
  result
24
25
  else
25
26
  if !nextParser.nil?
data/lib/Post.rb CHANGED
@@ -9,7 +9,7 @@ require 'date'
9
9
  class Post
10
10
 
11
11
  class PostInfo
12
- attr_accessor :title, :tags, :creator, :firstPublishedAt
12
+ attr_accessor :title, :tags, :creator, :firstPublishedAt, :latestPublishedAt
13
13
  end
14
14
 
15
15
  def self.getPostIDFromPostURLString(postURLString)
@@ -59,9 +59,14 @@ class Post
59
59
 
60
60
  firstPublishedAt = content&.dig("Post:#{postID}", "firstPublishedAt")
61
61
  if !firstPublishedAt.nil?
62
- postInfo.firstPublishedAt = DateTime.strptime(firstPublishedAt.to_s,'%Q')
62
+ postInfo.firstPublishedAt = Time.at(0, firstPublishedAt, :millisecond)
63
63
  end
64
-
64
+
65
+ latestPublishedAt = content&.dig("Post:#{postID}", "latestPublishedAt")
66
+ if !latestPublishedAt.nil?
67
+ postInfo.latestPublishedAt = Time.at(0, latestPublishedAt, :millisecond)
68
+ end
69
+
65
70
  postInfo
66
71
  end
67
72
  end
@@ -1,12 +1,8 @@
1
- #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
1
+
3
2
 
4
3
  $lib = File.expand_path('../lib', File.dirname(__FILE__))
5
- $LOAD_PATH.unshift($lib)
6
4
 
7
- require "open-uri"
8
- require 'json'
9
- require 'optparse'
5
+ require "fileutils"
10
6
 
11
7
  require "Parsers/H1Parser"
12
8
  require "Parsers/H2Parser"
@@ -31,26 +27,6 @@ require "Request"
31
27
  require "Post"
32
28
  require "User"
33
29
 
34
- class Main
35
- def initialize
36
- fetcher = ZMediumFetcher.new
37
- ARGV << '-h' if ARGV.empty?
38
- OptionParser.new do |opts|
39
- opts.banner = "Usage: ZMediumFetcher [options]"
40
-
41
- opts.on('-uUSERNAME', '--username=USERNAME', 'test') do |username|
42
- pathPolicy = PathPolicy.new("#{File.expand_path('../', File.dirname(__FILE__))}", "Output")
43
- fetcher.downloadPostsByUsername(username, pathPolicy)
44
- end
45
-
46
- opts.on('-pPOST_URL', '--postURL=POST_URL', 'test') do |postURL|
47
- pathPolicy = PathPolicy.new("#{File.expand_path('../', File.dirname(__FILE__))}", "Output")
48
- fetcher.downloadPost(postURL, pathPolicy)
49
- end
50
- end.parse!
51
- end
52
- end
53
-
54
30
  class ZMediumFetcher
55
31
 
56
32
  attr_accessor :progress, :linkParser
@@ -236,36 +212,48 @@ class ZMediumFetcher
236
212
  progress.printLog()
237
213
 
238
214
  absolutePath = postPathPolicy.getAbsolutePath("#{postPath}.md")
239
- Helper.createDirIfNotExist(postPathPolicy.getAbsolutePath(nil))
240
- index = 0
241
- File.open(absolutePath, "w+") do |file|
242
- # write postInfo into top
243
-
244
- file.puts(Helper.createPostInfo(postInfo))
245
-
246
- paragraphs.each do |paragraph|
247
- markupParser = MarkupParser.new(postHtml, paragraph)
248
- paragraph.text = markupParser.parse()
249
- result = startParser.parse(paragraph)
250
215
 
251
- if !linkParser.nil?
252
- result = linkParser.parse(result, paragraph.markupLinks)
253
- end
216
+ # if user latest use's version is < latest local version than force download (don't skip, make sure bug fixed can be influenced)
217
+ forceDownload = Helper.compareVersion(Helper.getLocalVersionFromGemspec(), Helper.getLocalVersionFromFile())
218
+
219
+ # if markdown file is exists and last modification time is >= latestPublishedAt(last update post time on medium)
220
+ if forceDownload == false && File.file?(absolutePath) && File.mtime(absolutePath) >= postInfo.latestPublishedAt
221
+ # Already downloaded and nothing has changed!, Skip!
222
+ progress.currentPostParagraphIndex = paragraphs.length
223
+ progress.message = "Skip, Post already downloaded and nothing has changed!"
224
+ progress.printLog()
225
+ else
226
+ Helper.createDirIfNotExist(postPathPolicy.getAbsolutePath(nil))
227
+ File.open(absolutePath, "w+") do |file|
228
+ # write postInfo into top
229
+ file.puts(Helper.createPostInfo(postInfo))
254
230
 
255
- file.puts(result)
256
-
257
- index += 1
258
- progress.currentPostParagraphIndex = index
259
- progress.message = "Converting Post..."
260
- progress.printLog()
231
+ index = 0
232
+ paragraphs.each do |paragraph|
233
+ markupParser = MarkupParser.new(postHtml, paragraph)
234
+ paragraph.text = markupParser.parse()
235
+ result = startParser.parse(paragraph)
236
+
237
+ if !linkParser.nil?
238
+ result = linkParser.parse(result, paragraph.markupLinks)
239
+ end
240
+
241
+ file.puts(result)
242
+
243
+ index += 1
244
+ progress.currentPostParagraphIndex = index
245
+ progress.message = "Converting Post..."
246
+ progress.printLog()
247
+ end
248
+
249
+ file.puts(Helper.createWatermark(postURL))
261
250
  end
251
+ FileUtils.touch absolutePath, :mtime => postInfo.latestPublishedAt
262
252
 
263
- file.puts(Helper.createWatermark(postURL))
253
+ progress.message = "Post Successfully Downloaded!"
254
+ progress.printLog()
264
255
  end
265
-
266
- progress.message = "Post Successfully Downloaded!"
267
- progress.printLog()
268
-
256
+
269
257
  progress.postPath = nil
270
258
  end
271
259
 
@@ -313,18 +301,4 @@ class ZMediumFetcher
313
301
  progress.message = "All posts has been downloaded!, Total posts: #{postURLS.length}"
314
302
  progress.printLog()
315
303
  end
316
- end
317
-
318
- begin
319
- puts "https://github.com/ZhgChgLi/ZMediumToMarkdown"
320
- puts "You have read and agree with the Disclaimer."
321
- Main.new()
322
- puts "https://github.com/ZhgChgLi/ZMediumToMarkdown"
323
- puts "Thanks for using this tool."
324
- puts "If this is helpful, please help to star the repo or recommend it to your friends."
325
- rescue => e
326
- puts "#Error: #{e.class} #{e.message}\n"
327
- puts e.backtrace
328
- puts "#Please feel free to open an Issue or submit a fix/contribution via Pull Request on:\n"
329
- puts "#https://github.com/ZhgChgLi/ZMediumToMarkdown\n"
330
304
  end
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.0.2
4
+ version: 1.2.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-05-28 00:00:00.000000000 Z
11
+ date: 2022-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -56,11 +56,11 @@ description: ZMediumToMarkdown lets you download Medium post and convert it to m
56
56
  format easily.
57
57
  email:
58
58
  executables:
59
- - ZMediumFetcher
59
+ - ZMediumToMarkdown
60
60
  extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
- - bin/ZMediumFetcher
63
+ - bin/ZMediumToMarkdown
64
64
  - lib/ErrorHandle.rb
65
65
  - lib/Helper.rb
66
66
  - lib/ImageDownloader.rb
@@ -87,6 +87,7 @@ files:
87
87
  - lib/Post.rb
88
88
  - lib/Request.rb
89
89
  - lib/User.rb
90
+ - lib/ZMediumFetcher.rb
90
91
  homepage: https://github.com/ZhgChgLi/ZMediumToMarkdown
91
92
  licenses:
92
93
  - MIT