ZMediumToMarkdown 1.0.2 → 1.2.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 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