ZMediumToMarkdown 2.4.0 → 2.4.2

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: c57f5610ede891d1c9677db7c4c3c0345bb5d309f5825538524d238db5b991c4
4
- data.tar.gz: d06da63e8bb12bb776959d93d9dddff1f407a9654cec1883916b94c7ddd6b2d9
3
+ metadata.gz: b853d78f150d3134ac412b310a53a864fa4808a7c6dd476c28f534ecc607de18
4
+ data.tar.gz: 886dcd5efb04f28a033eb6ca80ed2babaa2f37c9afc4d524a776b3f154d96f35
5
5
  SHA512:
6
- metadata.gz: 2437e85b4184dfe4e72e8923af91a7ae4f849e973f618c4a66d8ff7edd3fc09122f32cc11152f8a947fc74d0fbec1f751eff57d94e036ef3b19060252c08d088
7
- data.tar.gz: d374e8169f365f4934b2911a96028680dc2ab0f57edd3a3a07469876ec131d0429679b45f9ba52202544c048792551d2f9bca47478a4c79fbed102f75a11ee00
6
+ metadata.gz: 7492890c6dbacf64ea895246224692d73925359489fd97383c6331eb613201dc64963631a72eaa2ae708470ebf912199057f800428ca847284300da1bb091b46
7
+ data.tar.gz: 869962271b377b7e258bf013d7136befba33bb8a72272f5aee15e10af209e1be276028c344bfb2335d094f28bffaabff723c6fd8f600a6a5051e7baa0b5a9bf0
@@ -16,14 +16,14 @@ class Main
16
16
  fetcher = ZMediumFetcher.new
17
17
  ARGV << '-h' if ARGV.empty?
18
18
 
19
+ options = {}
19
20
  filePath = ENV['PWD'] || ::Dir.pwd
20
-
21
+
21
22
  OptionParser.new do |opts|
22
23
  opts.banner = "Usage: ZMediumFetcher [options]"
23
-
24
+
24
25
  opts.on('-s', '--cookie_sid COOKIESID', 'Your logged-in Medium cookie sid value') do |cookie_sid|
25
26
  $cookie_sid = cookie_sid
26
- puts $cookie_sid
27
27
  end
28
28
 
29
29
  opts.on('-d', '--cookie_uid COOKIEUID', 'Your logged-in Medium cookie uid value') do |cookie_uid|
@@ -31,58 +31,83 @@ class Main
31
31
  end
32
32
 
33
33
  opts.on('-u', '--username USERNAME', 'Downloading all posts from user') do |username|
34
- outputFilePath = PathPolicy.new("#{filePath}/Output", "Output")
35
- fetcher.downloadPostsByUsername(username, outputFilePath)
36
-
37
- Helper.printNewVersionMessageIfExists()
34
+ options[:u] = username
38
35
  end
39
36
 
40
37
  opts.on('-p', '--postURL POST_URL', 'Downloading single post') do |postURL|
41
- outputFilePath = PathPolicy.new("#{filePath}/Output", "Output")
42
- fetcher.downloadPost(postURL, outputFilePath, nil)
43
-
44
- Helper.printNewVersionMessageIfExists()
38
+ options[:p] = postURL
45
39
  end
46
40
 
47
41
  opts.on('-j', '--jekyllUsername USERNAME', 'Downloading all posts from user with Jekyll friendly') do |username|
48
- outputFilePath = PathPolicy.new(filePath, "")
49
- fetcher.isForJekyll = true
50
- fetcher.downloadPostsByUsername(username, outputFilePath)
51
-
52
- Helper.printNewVersionMessageIfExists()
42
+ options[:j] = username
53
43
  end
54
44
 
55
45
  opts.on('-k', '--jekyllPostURL POST_URL', 'Downloading single post with Jekyll friendly') do |postURL|
56
- outputFilePath = PathPolicy.new(filePath, "")
57
- fetcher.isForJekyll = true
58
- fetcher.downloadPost(postURL, outputFilePath, nil)
59
-
60
- Helper.printNewVersionMessageIfExists()
46
+ options[:k] = postURL
61
47
  end
62
48
 
63
49
  opts.on('-n', '--new', 'Update to latest version') do
64
- if Helper.getRemoteVersionFromGithub() > Helper.getLocalVersion()
65
- Helper.downloadLatestVersion()
66
- else
67
- puts "You're using the latest version :)"
68
- end
50
+ options[:n] = true
69
51
  end
70
52
 
71
53
  opts.on('-c', '--clean', 'Remove all downloaded posts data') do
72
- outputFilePath = PathPolicy.new(filePath, "")
73
- FileUtils.rm_rf(Dir[outputFilePath.getAbsolutePath(nil)])
74
- puts "All downloaded posts data has been removed."
75
-
76
- Helper.printNewVersionMessageIfExists()
54
+ options[:c] = true
77
55
  end
78
56
 
79
57
  opts.on('-v', '--version', 'Print current ZMediumToMarkdown Version & Output Path') do
80
- puts "Version:#{Helper.getLocalVersion().to_s}"
81
-
82
- Helper.printNewVersionMessageIfExists()
58
+ options[:v] = true
83
59
  end
84
-
85
60
  end.parse!
61
+
62
+ #
63
+ if !options[:v].nil? && options[:v] == true
64
+ puts "Version:#{Helper.getLocalVersion().to_s}"
65
+
66
+ Helper.printNewVersionMessageIfExists()
67
+ elsif !options[:c].nil? && options[:c] == true
68
+ outputFilePath = PathPolicy.new(filePath, "")
69
+ FileUtils.rm_rf(Dir[outputFilePath.getAbsolutePath(nil)])
70
+ puts "All downloaded posts data has been removed."
71
+
72
+ Helper.printNewVersionMessageIfExists()
73
+ elsif !options[:n].nil? && options[:n] == true
74
+ if Helper.getRemoteVersionFromGithub() > Helper.getLocalVersion()
75
+ Helper.downloadLatestVersion()
76
+ else
77
+ puts "You're using the latest version :)"
78
+ end
79
+ elsif !options[:k].nil?
80
+ postURL = options[:k]
81
+
82
+ outputFilePath = PathPolicy.new(filePath, "")
83
+ fetcher.isForJekyll = true
84
+ fetcher.downloadPost(postURL, outputFilePath, nil)
85
+
86
+ Helper.printNewVersionMessageIfExists()
87
+ elsif !options[:j].nil?
88
+ username = options[:j]
89
+
90
+ outputFilePath = PathPolicy.new(filePath, "")
91
+ fetcher.isForJekyll = true
92
+ fetcher.downloadPostsByUsername(username, outputFilePath)
93
+
94
+ Helper.printNewVersionMessageIfExists()
95
+ elsif !options[:p].nil?
96
+ postURL = options[:p]
97
+
98
+ outputFilePath = PathPolicy.new("#{filePath}/Output", "Output")
99
+ fetcher.downloadPost(postURL, outputFilePath, nil)
100
+
101
+ Helper.printNewVersionMessageIfExists()
102
+ elsif !options[:u].nil?
103
+ username = options[:u]
104
+
105
+ outputFilePath = PathPolicy.new("#{filePath}/Output", "Output")
106
+ fetcher.downloadPostsByUsername(username, outputFilePath)
107
+
108
+ Helper.printNewVersionMessageIfExists()
109
+ end
110
+
86
111
  end
87
112
  end
88
113
 
data/lib/Helper.rb CHANGED
@@ -99,7 +99,7 @@ class Helper
99
99
  end
100
100
  end
101
101
 
102
- def self.createPostInfo(postInfo, isPin, isForJekyll)
102
+ def self.createPostInfo(postInfo, isPin, isLockedPreviewOnly, isForJekyll)
103
103
  title = postInfo.title&.gsub("[","")
104
104
  title = title&.gsub("]","")
105
105
 
@@ -123,6 +123,9 @@ class Helper
123
123
  if !isPin.nil? && isPin == true
124
124
  result += "pin: true\r\n"
125
125
  end
126
+ if !isLockedPreviewOnly.nil? && isLockedPreviewOnly == true
127
+ result += "lockedPreviewOnly: true\r\n"
128
+ end
126
129
 
127
130
  if isForJekyll
128
131
  result += "render_with_liquid: false\n"
@@ -211,4 +214,17 @@ class Helper
211
214
 
212
215
  text
213
216
  end
217
+
218
+ def self.createViewFullPost(postURL, isForJekyll)
219
+ jekyllOpen = ""
220
+ if isForJekyll
221
+ jekyllOpen = "{:target=\"_blank\"}"
222
+ end
223
+
224
+ text = "\r\n\r\n\r\n"
225
+ text += "**This [post](#{postURL})#{jekyllOpen} is behind Medium's paywall, View the full [post](#{postURL})#{jekyllOpen} on Medium, converted by [ZMediumToMarkdown](https://github.com/ZhgChgLi/ZMediumToMarkdown)#{jekyllOpen}.**"
226
+ text += "\r\n"
227
+
228
+ text
229
+ end
214
230
  end
@@ -76,20 +76,28 @@ class IframeParser < Parser
76
76
  gist.gsub! '\"', '"'
77
77
  gist.gsub! '<\/', '</'
78
78
  gistHTML = Nokogiri::HTML(gist)
79
- lang = gistHTML.search('table').first['data-tagsearch-lang'].downcase
80
- if isForJekyll and lang == "objective-c"
81
- lang = "objectivec"
82
- end
83
- gistHTML.search('a').each do |a|
84
- if a.text == 'view raw'
85
- gistRAW = Request.body(Request.URL(a['href']))
79
+
80
+ lang = gistHTML.search('table').first['data-tagsearch-lang']
86
81
 
87
- result = "```#{lang}\n"
82
+ if !lang.nil?
83
+ lang = lang.downcase
84
+ if isForJekyll and lang == "objective-c"
85
+ lang = "objectivec"
86
+ end
87
+ gistHTML.search('a').each do |a|
88
+ if a.text == 'view raw'
89
+ gistRAW = Request.body(Request.URL(a['href']))
88
90
 
89
- result += gistRAW.chomp
90
-
91
- result += "\n```"
91
+ result = "```#{lang}\n"
92
+
93
+ result += gistRAW.chomp
94
+
95
+ result += "\n```"
96
+ end
92
97
  end
98
+ else
99
+ clean_url = srce.to_s.gsub(/\.js$/, '')
100
+ result = "[#{clean_url}](#{clean_url})#{jekyllOpen}"
93
101
  end
94
102
  else
95
103
  ogURL = url
@@ -156,11 +156,6 @@ class ZMediumFetcher
156
156
 
157
157
  isLockedPreviewOnly = contentInfo&.dig("isLockedPreviewOnly")
158
158
 
159
- if isLockedPreviewOnly
160
- puts "Skip: This post is listed in Medium's paywall. You need to provide Medium Member vaild logged-in cookies to access it (refer to Readme.md). PostURL: #{postURL}"
161
- return
162
- end
163
-
164
159
  sourceParagraphs = contentInfo&.dig("bodyModel", "paragraphs")
165
160
 
166
161
  if sourceParagraphs.nil?
@@ -249,6 +244,7 @@ class ZMediumFetcher
249
244
 
250
245
  fileLatestPublishedAt = nil
251
246
  filePin = false
247
+ fileLockedPreviewOnly = false
252
248
  if File.file?(absolutePath)
253
249
  lines = File.foreach(absolutePath).first(15)
254
250
  if lines.first&.start_with?("---")
@@ -261,10 +257,15 @@ class ZMediumFetcher
261
257
  if !pinLine.nil?
262
258
  filePin = pinLine[/^(pin:)\s+(\S*)/, 2].downcase == "true"
263
259
  end
260
+
261
+ lockedPreviewOnlyLine = lines.select { |line| line.start_with?("lockedPreviewOnly:") }.first
262
+ if !lockedPreviewOnlyLine.nil?
263
+ fileLockedPreviewOnly = lockedPreviewOnlyLine[/^(lockedPreviewOnly:)\s+(\S*)/, 2].downcase == "true"
264
+ end
264
265
  end
265
266
  end
266
267
 
267
- if (!fileLatestPublishedAt.nil? && fileLatestPublishedAt >= postInfo.latestPublishedAt.to_i) && (!isPin.nil? && isPin == filePin)
268
+ if (!fileLatestPublishedAt.nil? && fileLatestPublishedAt >= postInfo.latestPublishedAt.to_i) && (!isPin.nil? && isPin == filePin) && (!isLockedPreviewOnly.nil? && isLockedPreviewOnly == fileLockedPreviewOnly)
268
269
  # Already downloaded and nothing has changed!, Skip!
269
270
  progress.currentPostParagraphIndex = paragraphs.length
270
271
  progress.message = "Skip, Post already downloaded and nothing has changed!"
@@ -273,7 +274,7 @@ class ZMediumFetcher
273
274
  Helper.createDirIfNotExist(postPathPolicy.getAbsolutePath(nil))
274
275
  File.open(absolutePath, "w+") do |file|
275
276
  # write postInfo into top
276
- postMetaInfo = Helper.createPostInfo(postInfo, isPin, isForJekyll)
277
+ postMetaInfo = Helper.createPostInfo(postInfo, isPin, isLockedPreviewOnly, isForJekyll)
277
278
  if !postMetaInfo.nil?
278
279
  file.puts(postMetaInfo)
279
280
  end
@@ -296,15 +297,29 @@ class ZMediumFetcher
296
297
  progress.message = "Converting Post..."
297
298
  progress.printLog()
298
299
  end
299
-
300
- postWatermark = Helper.createWatermark(postURL, isForJekyll)
301
- if !postWatermark.nil?
302
- file.puts(postWatermark)
300
+
301
+ if isLockedPreviewOnly
302
+ viewFullPost = Helper.createViewFullPost(postURL, isForJekyll)
303
+ if !viewFullPost.nil?
304
+ file.puts(viewFullPost)
305
+ end
306
+ else
307
+ postWatermark = Helper.createWatermark(postURL, isForJekyll)
308
+ if !postWatermark.nil?
309
+ file.puts(postWatermark)
310
+ end
303
311
  end
312
+
313
+
304
314
  end
305
315
  FileUtils.touch absolutePath, :mtime => postInfo.latestPublishedAt
306
316
 
307
- progress.message = "Post Successfully Downloaded!"
317
+ if isLockedPreviewOnly
318
+ progress.message = "This post is behind Medium's paywall. You need to provide valid Medium Member login cookies to download the full post."
319
+ else
320
+ progress.message = "Post Successfully Downloaded!"
321
+ end
322
+
308
323
  progress.printLog()
309
324
  end
310
325
 
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: 2.4.0
4
+ version: 2.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ZhgChgLi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-10 00:00:00.000000000 Z
11
+ date: 2024-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri