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 +4 -4
- data/bin/ZMediumToMarkdown +60 -35
- data/lib/Helper.rb +17 -1
- data/lib/Parsers/IframeParser.rb +19 -11
- data/lib/ZMediumFetcher.rb +27 -12
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b853d78f150d3134ac412b310a53a864fa4808a7c6dd476c28f534ecc607de18
|
4
|
+
data.tar.gz: 886dcd5efb04f28a033eb6ca80ed2babaa2f37c9afc4d524a776b3f154d96f35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7492890c6dbacf64ea895246224692d73925359489fd97383c6331eb613201dc64963631a72eaa2ae708470ebf912199057f800428ca847284300da1bb091b46
|
7
|
+
data.tar.gz: 869962271b377b7e258bf013d7136befba33bb8a72272f5aee15e10af209e1be276028c344bfb2335d094f28bffaabff723c6fd8f600a6a5051e7baa0b5a9bf0
|
data/bin/ZMediumToMarkdown
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/Parsers/IframeParser.rb
CHANGED
@@ -76,20 +76,28 @@ class IframeParser < Parser
|
|
76
76
|
gist.gsub! '\"', '"'
|
77
77
|
gist.gsub! '<\/', '</'
|
78
78
|
gistHTML = Nokogiri::HTML(gist)
|
79
|
-
|
80
|
-
|
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
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
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
|
data/lib/ZMediumFetcher.rb
CHANGED
@@ -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
|
-
|
301
|
-
|
302
|
-
|
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
|
-
|
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.
|
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-
|
11
|
+
date: 2024-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|