jekyll-chatgpt-translate 0.0.21 → 0.0.22

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: bae88d4bb6c95da76a68c64321f5d308611a19981158f69cd2aa8763d0f4f8f0
4
- data.tar.gz: b820a3d53adafd3ea91f365e95851bf848e05890281d1cc7d85bc6a19692af3b
3
+ metadata.gz: daa42e099235943fc1a5473a83796abe90b7949d1365c9d9b7349c7c86be7406
4
+ data.tar.gz: 6c7559aea364339a8b2ac5eac397e314491166b77cfff92565218f6cdd04499b
5
5
  SHA512:
6
- metadata.gz: 554c9a981763d2957c83b396098fec3b75c23fd98f73a180b33528db97a43406cc2b6595893b1e848a59829e614ec4eb4c70f50d63301d6b93047caf12a81e19
7
- data.tar.gz: 695cbae5292d6e81ad69d81657e5ded96f69f2c970bfa2d0ad4b8da23c8c8f412cd77e3944ec09e064417114b0c2ae3518b61b80c3af3a2d4d376e0d0dd8c6b0
6
+ metadata.gz: e651bfae3d35ddf473555eb168cf3301ba6dacda8352fd00a610613c9a2dc8821a1188064089f701ae94c4e4b2277f41b5d635842ae4132f92e9242828ecc0ac
7
+ data.tar.gz: a18e7007a9f40cfdba340285c8ef665c8c47d8e829ac6f76d304b77cec89b14ce9e9c1d56ddfd72f010429d4620f712ee773ed7011942d771c49993799bcef23
data/features/cli.feature CHANGED
@@ -31,6 +31,11 @@ Feature: Simple site building
31
31
  Chinese: {{ content }}
32
32
  The original: {{ page.translated-original-url }}
33
33
  """
34
+ And I have a "_layouts/translated.html" file with content:
35
+ """
36
+ French: {{ content }}
37
+ The original: {{ page.translated-original-url }}
38
+ """
34
39
  And I have a "_posts/2023-01-01-hello.md" file with content:
35
40
  """
36
41
  ---
@@ -50,3 +55,33 @@ Feature: Simple site building
50
55
  And File "_site/2023-01-01-hello-chinese.html" contains "The original: /2023/01/01/hello.html"
51
56
  And File "_site/2023/hello-french.html" exists
52
57
 
58
+ Scenario: Simple download of existing page
59
+ Given I have a "_config.yml" file with content:
60
+ """
61
+ url: https://www.yegor256.com
62
+ markdown: kramdown
63
+ plugins:
64
+ - jekyll-chatgpt-translate
65
+ chatgpt-translate:
66
+ source: en
67
+ version: ""
68
+ api_key: "it-is-not-used, because EN to EN translation"
69
+ layout: should-not-be-used
70
+ targets:
71
+ -
72
+ language: en
73
+ permalink: about-me.html
74
+ """
75
+ And I have a "_posts/2023-01-01-hello.md" file with content:
76
+ """
77
+ ---
78
+ title: foo
79
+ ---
80
+ foo
81
+ """
82
+ Then I build Jekyll site
83
+ And Exit code is zero
84
+ And Stdout contains "No need to translate, the page exists"
85
+ And File "_site/2023/01/01/hello.html" exists
86
+ And File "_site/about-me.html" exists
87
+ And File "_site/about-me.html" contains "Yegor Bugayenko"
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
29
29
  s.required_ruby_version = '>= 2.6'
30
30
  s.name = 'jekyll-chatgpt-translate'
31
- s.version = '0.0.21'
31
+ s.version = '0.0.22'
32
32
  s.license = 'MIT'
33
33
  s.summary = 'Translate Jekyll Pages Through ChatGPT'
34
34
  s.description = [
@@ -81,9 +81,8 @@ class GptTranslate::Generator < Jekyll::Generator
81
81
  '---'
82
82
  ].join("\n")
83
83
  )
84
- url = Jekyll::Page.new(site, site.source, File.dirname(path), File.basename(path)).url
85
84
  ping = GptTranslate::Ping.new(site, link)
86
- if config['no_download'].nil? && ping.found?(File.join(site.dest, url), version.empty? ? '' : marker)
85
+ if config['no_download'].nil? && ping.found?(version.empty? ? '' : marker)
87
86
  copied += 1
88
87
  elsif translated >= threshold
89
88
  next
@@ -113,7 +112,8 @@ class GptTranslate::Generator < Jekyll::Generator
113
112
  doc.data['chatgpt-model'] = model
114
113
  end
115
114
  end
116
- Jekyll.logger.info("#{translated} pages translated and #{copied} pages copied in #{(Time.now - start).round(2)}s")
115
+ Jekyll.logger.info("jekyll-chatgpt-translate #{GptTranslate::VERSION}: \
116
+ #{translated} pages translated and #{copied} pages copied in #{(Time.now - start).round(2)}s")
117
117
  end
118
118
 
119
119
  private
@@ -134,6 +134,10 @@ class GptTranslate::Generator < Jekyll::Generator
134
134
  Jekyll.logger.info("The file with the OpenAI API key is not found: #{file.inspect}")
135
135
  nil
136
136
  end
137
+ if key.nil? && config['api_key']
138
+ Jekyll.logger.info("The OpenAI API key is found in 'api_key' of _config.yml")
139
+ key = config['api_key']
140
+ end
137
141
  if key.nil? && Jekyll.env == 'development'
138
142
  Jekyll.logger.info("OPENAI_API_KEY environment variable is not set, \
139
143
  the `api_key_file` option is not specified in the _config.yml, and \
@@ -25,6 +25,7 @@
25
25
  require 'iri'
26
26
  require 'net/http'
27
27
  require 'uri'
28
+ require 'jekyll'
28
29
  require 'fileutils'
29
30
  require_relative 'version'
30
31
 
@@ -47,7 +48,7 @@ class GptTranslate::Ping
47
48
  @path = path
48
49
  end
49
50
 
50
- def found?(file, marker)
51
+ def found?(marker)
51
52
  home = @site.config['url']
52
53
  return false if home.nil?
53
54
  uri = Iri.new(home).path(@path).to_s
@@ -57,9 +58,8 @@ class GptTranslate::Ping
57
58
  html = before.body
58
59
  if html.include?(marker)
59
60
  Jekyll.logger.info("No need to translate, the page exists at \
60
- #{uri.inspect} (#{html.split.count} words), saved to #{file.inspect}")
61
- FileUtils.mkdir_p(File.dirname(file))
62
- File.write(file, html)
61
+ #{uri.inspect} (#{html.split.count} words)")
62
+ @site.static_files << DownloadedFile.new(@site, @path, html)
63
63
  return true
64
64
  end
65
65
  Jekyll.logger.info("Re-translation required for #{uri.inspect}")
@@ -67,10 +67,25 @@ class GptTranslate::Ping
67
67
  Jekyll.logger.info("The page is absent, will translate #{uri.inspect} (#{before.code})")
68
68
  end
69
69
  Jekyll.logger.debug("GET #{uri.inspect}: #{before.code}")
70
- rescue StandardError => e
70
+ rescue Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL => e
71
71
  Jekyll.logger.debug("Failed to ping #{uri.inspect}: #{e.message}")
72
72
  Jekyll.logger.info("The page is absent (#{e.class.name}): #{uri.inspect}")
73
73
  end
74
74
  false
75
75
  end
76
+
77
+ # The file we just downloaded.
78
+ class DownloadedFile < Jekyll::StaticFile
79
+ def initialize(site, path, html)
80
+ super(site, site.dest, '', path)
81
+ @html = html
82
+ end
83
+
84
+ def write(_dest)
85
+ FileUtils.mkdir_p(File.dirname(path))
86
+ File.write(path, @html)
87
+ Jekyll.logger.info("Saved #{@html.split.count} words to #{path.inspect}")
88
+ true
89
+ end
90
+ end
76
91
  end
@@ -23,5 +23,5 @@
23
23
  # SOFTWARE.
24
24
 
25
25
  module GptTranslate
26
- VERSION = '0.0.21'
26
+ VERSION = '0.0.22'
27
27
  end
data/test/test__helper.rb CHANGED
@@ -27,3 +27,107 @@ SimpleCov.start
27
27
 
28
28
  require 'jekyll'
29
29
  Jekyll.logger.adjust_verbosity(verbose: true)
30
+
31
+ # The module we are in.
32
+ module GptTranslate; end
33
+
34
+ # Fake.
35
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
36
+ # Copyright:: Copyright (c) 2023 Yegor Bugayenko
37
+ # License:: MIT
38
+ class GptTranslate::FakeSite
39
+ attr_reader :config, :pages, :static_files
40
+
41
+ def initialize(config, docs = [])
42
+ @config = config
43
+ @docs = docs
44
+ @pages = []
45
+ @static_files = []
46
+ end
47
+
48
+ def posts
49
+ GptTranslate::FakePosts.new(@docs)
50
+ end
51
+
52
+ def permalink_style
53
+ ''
54
+ end
55
+
56
+ def frontmatter_defaults
57
+ Jekyll::FrontmatterDefaults.new(self)
58
+ end
59
+
60
+ def converters
61
+ [Jekyll::Converters::Markdown.new({ 'markdown_ext' => 'md' })]
62
+ end
63
+
64
+ def source
65
+ ''
66
+ end
67
+
68
+ def dest
69
+ return '' if @docs.empty?
70
+ File.dirname(@docs[0])
71
+ end
72
+
73
+ def in_theme_dir(base, _foo = nil, _bar = nil)
74
+ base
75
+ end
76
+
77
+ def in_dest_dir(*paths)
78
+ paths[0].dup
79
+ end
80
+ end
81
+
82
+ # Fake.
83
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
84
+ # Copyright:: Copyright (c) 2023 Yegor Bugayenko
85
+ # License:: MIT
86
+ class GptTranslate::FakeDocument
87
+ attr_reader :data
88
+
89
+ def initialize(path)
90
+ @path = path
91
+ @data = { 'date' => Time.now, 'title' => 'Hello!' }
92
+ end
93
+
94
+ def content
95
+ 'Hello, world!'
96
+ end
97
+
98
+ def []=(key, value)
99
+ @data[key] = value
100
+ end
101
+
102
+ def [](key)
103
+ @data[key] || ''
104
+ end
105
+
106
+ def relative_path
107
+ @path
108
+ end
109
+
110
+ def url
111
+ '2023-01-01-hello.html'
112
+ end
113
+
114
+ def basename
115
+ '2023-01-01-hello.md'
116
+ end
117
+ end
118
+
119
+ # Fake.
120
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
121
+ # Copyright:: Copyright (c) 2023 Yegor Bugayenko
122
+ # License:: MIT
123
+ class GptTranslate::FakePosts
124
+ attr_reader :config
125
+
126
+ def initialize(docs)
127
+ @docs = docs
128
+ end
129
+
130
+ def docs
131
+ @docs.map { |d| GptTranslate::FakeDocument.new(d) }
132
+ end
133
+ end
@@ -33,98 +33,11 @@ require_relative '../lib/jekyll-chatgpt-translate/generator'
33
33
  # Copyright:: Copyright (c) 2023 Yegor Bugayenko
34
34
  # License:: MIT
35
35
  class GptTranslate::GeneratorTest < Minitest::Test
36
- class FakeSite
37
- attr_reader :config, :pages
38
-
39
- def initialize(config, docs)
40
- @config = config
41
- @docs = docs
42
- @pages = []
43
- end
44
-
45
- def posts
46
- FakePosts.new(@docs)
47
- end
48
-
49
- def permalink_style
50
- ''
51
- end
52
-
53
- def frontmatter_defaults
54
- Jekyll::FrontmatterDefaults.new(self)
55
- end
56
-
57
- def converters
58
- [Jekyll::Converters::Markdown.new({ 'markdown_ext' => 'md' })]
59
- end
60
-
61
- def source
62
- ''
63
- end
64
-
65
- def dest
66
- File.dirname(@docs[0])
67
- end
68
-
69
- def in_theme_dir(base, _foo = nil, _bar = nil)
70
- base
71
- end
72
-
73
- def in_dest_dir(*paths)
74
- paths[0].dup
75
- end
76
- end
77
-
78
- class FakeDocument
79
- attr_reader :data
80
-
81
- def initialize(path)
82
- @path = path
83
- @data = { 'date' => Time.now, 'title' => 'Hello!' }
84
- end
85
-
86
- def content
87
- 'Hello, world!'
88
- end
89
-
90
- def []=(key, value)
91
- @data[key] = value
92
- end
93
-
94
- def [](key)
95
- @data[key] || ''
96
- end
97
-
98
- def relative_path
99
- @path
100
- end
101
-
102
- def url
103
- '2023-01-01-hello.html'
104
- end
105
-
106
- def basename
107
- '2023-01-01-hello.md'
108
- end
109
- end
110
-
111
- class FakePosts
112
- attr_reader :config
113
-
114
- def initialize(docs)
115
- @docs = docs
116
- end
117
-
118
- def docs
119
- @docs.map { |d| FakeDocument.new(d) }
120
- end
121
- end
122
-
123
36
  def test_simple_scenario
124
37
  Dir.mktmpdir do |home|
125
38
  post = File.join(home, '2023-01-01-hello.md')
126
39
  File.write(post, "---\ntitle: Hello\n---\n\nHello, world!")
127
- site = FakeSite.new(
40
+ site = GptTranslate::FakeSite.new(
128
41
  {
129
42
  'url' => 'https://www.yegor256.com/',
130
43
  'chatgpt-translate' => {
@@ -150,7 +63,7 @@ class GptTranslate::GeneratorTest < Minitest::Test
150
63
  Dir.mktmpdir do |home|
151
64
  post = File.join(home, '2023-01-01-hello.md')
152
65
  File.write(post, "---\ntitle: Hello\n---\n\nHello, world!")
153
- site = FakeSite.new(
66
+ site = GptTranslate::FakeSite.new(
154
67
  {
155
68
  'chatgpt-translate' => {
156
69
  'threshold' => 1,
data/test/test_ping.rb CHANGED
@@ -34,39 +34,28 @@ require_relative '../lib/jekyll-chatgpt-translate/ping'
34
34
  # Copyright:: Copyright (c) 2023 Yegor Bugayenko
35
35
  # License:: MIT
36
36
  class GptTranslate::PingTest < Minitest::Test
37
- class FakeSite
38
- attr_reader :config
39
-
40
- def initialize(config)
41
- @config = config
42
- end
43
- end
44
-
45
37
  def test_when_exists
46
- stub_request(:any, 'https://www.yegor256.com/about-me.html')
47
- site = FakeSite.new({ 'url' => 'https://www.yegor256.com/' })
38
+ stub_request(:any, 'https://www.yegor256.com/about-me.html').to_return(body: 'Hello!')
39
+ site = GptTranslate::FakeSite.new({ 'url' => 'https://www.yegor256.com/' })
48
40
  ping = GptTranslate::Ping.new(site, '/about-me.html')
49
- Tempfile.open do |f|
50
- assert(ping.found?(f, ''))
51
- end
41
+ assert(ping.found?(''))
42
+ assert_equal(1, site.static_files.size)
52
43
  end
53
44
 
54
45
  def test_when_not_exists
55
46
  stub_request(:any, 'https://www.yegor256.com/absent.html').to_return(status: 404)
56
- site = FakeSite.new({ 'url' => 'https://www.yegor256.com/' })
47
+ site = GptTranslate::FakeSite.new({ 'url' => 'https://www.yegor256.com/' })
57
48
  ping = GptTranslate::Ping.new(site, '/absent.html')
58
- Tempfile.open do |f|
59
- assert(!ping.found?(f, ''))
60
- end
49
+ assert(!ping.found?(''))
50
+ assert_equal(0, site.static_files.size)
61
51
  end
62
52
 
63
53
  def test_wrong_address
64
54
  WebMock.allow_net_connect!
65
- site = FakeSite.new({ 'url' => 'https://localhost:1/' })
55
+ site = GptTranslate::FakeSite.new({ 'url' => 'https://localhost:1/' })
66
56
  ping = GptTranslate::Ping.new(site, '/boom.html')
67
- Tempfile.open do |f|
68
- assert(!ping.found?(f, ''))
69
- end
57
+ assert(!ping.found?(''))
58
+ assert_equal(0, site.static_files.size)
70
59
  end
71
60
 
72
61
  def test_relative_path
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-chatgpt-translate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.21
4
+ version: 0.0.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko