jekyll-chatgpt-translate 0.0.17 → 0.0.19
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/.rubocop.yml +2 -0
- data/README.md +13 -0
- data/features/step_definitions/steps.rb +6 -10
- data/jekyll-chatgpt-translate.gemspec +1 -1
- data/lib/jekyll-chatgpt-translate/chatgpt.rb +3 -3
- data/lib/jekyll-chatgpt-translate/generator.rb +34 -32
- data/lib/jekyll-chatgpt-translate/plain.rb +10 -1
- data/lib/jekyll-chatgpt-translate/version.rb +1 -1
- data/test/test_generator.rb +6 -11
- data/test/test_plain.rb +13 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7cc9cfc295b4eeb123b972094f4fa1c648a88f3df384a78b489b9b0bafbd0c1
|
4
|
+
data.tar.gz: 06cd12eabf0fbf6e77a64f52384609bcdc33edb8c6324aa4555de4f7fb275c99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d0b55a94c132688afe28b9edbc4115570e6fd449b001bc606bf33c9d30712f2c1639fa8e0334652c0e8aa36b79e356f40845162e810e5b980f8b2dbcd7641746
|
7
|
+
data.tar.gz: e058ea19c7ffb630ab48bac0b433c8fde5f5b76d6087833cb2f7a70c04eaaca32f7273cacd881caf7b3b9355b5cb6a15f539060ff14bd3184baf5a6214b79914
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
[](http://badge.fury.io/rb/glogin)
|
1
2
|
<img src="logo.png" style="width:256px;"/>
|
2
3
|
|
3
4
|
[](https://github.com/yegor256/jekyll-chatgpt-translate/actions/workflows/rake.yml)
|
@@ -50,6 +51,8 @@ to get the URL of the page that was translated.
|
|
50
51
|
|
51
52
|
You can also use `{{ page.chatgpt-model }}`
|
52
53
|
inside both the original page and the translated one, to refer to the model of ChatGPT.
|
54
|
+
The presence of this attribute in the `{{ page }}` means that the
|
55
|
+
page was translated or the translated HTML was downloaded and placed into the `_site` directory.
|
53
56
|
|
54
57
|
## Options
|
55
58
|
|
@@ -62,6 +65,16 @@ Full list of options available to specify in `_config.yml`:
|
|
62
65
|
|
63
66
|
* `source` (optional) — is the ISO-839-1 code of the source language.
|
64
67
|
|
68
|
+
* `no_download` (optional) — if this attribute is present, the plugin won't try
|
69
|
+
to find HTML versions of translated pages in the Internet and won't try to
|
70
|
+
download them and place into the `_site` directory. Thus, your entire site
|
71
|
+
will have to be re-translated on every build (might be very ineffective if the site is big!)
|
72
|
+
|
73
|
+
* `min_chars` (optional) — minimum number of chars that must be present in
|
74
|
+
a paragraph in order for it to be feasible to go to ChatGPT. The robot
|
75
|
+
doesn't translate short paragraphs pretty enough. It's better to keep this
|
76
|
+
number big enough, to avoid silly translations. The default is 128.
|
77
|
+
|
65
78
|
* `layout` (optional) — is name of the file in `_layouts` directory, without the extension.
|
66
79
|
This layout will be specified for the pages generated by this plugin.
|
67
80
|
|
@@ -40,7 +40,7 @@ Given(/^I have a "([^"]*)" file with content:$/) do |file, text|
|
|
40
40
|
File.write(file, text.gsub('\\xFF', 0xFF.chr))
|
41
41
|
end
|
42
42
|
|
43
|
-
When(
|
43
|
+
When('I build Jekyll site') do
|
44
44
|
@stdout = `jekyll build`
|
45
45
|
@exitstatus = $CHILD_STATUS.exitstatus
|
46
46
|
end
|
@@ -59,20 +59,16 @@ Then('File {string} contains {string}') do |string, string2|
|
|
59
59
|
raise "The file \"#{string}\" doesn't contain \"#{string2}\":\n#{content}" unless content.include?(string2)
|
60
60
|
end
|
61
61
|
|
62
|
-
Then(
|
63
|
-
raise "STDOUT is not empty:\n#{@stdout}" unless @stdout == ''
|
64
|
-
end
|
65
|
-
|
66
|
-
Then(/^Exit code is zero$/) do
|
62
|
+
Then('Exit code is zero') do
|
67
63
|
raise "Non-zero exit #{@exitstatus}:\n#{@stdout}" unless @exitstatus.zero?
|
68
64
|
end
|
69
65
|
|
70
|
-
Then(
|
66
|
+
Then('Exit code is not zero') do
|
71
67
|
raise 'Zero exit code' if @exitstatus.zero?
|
72
68
|
end
|
73
69
|
|
74
|
-
When(
|
75
|
-
@stdout = `#{
|
70
|
+
When('I run bash with {string}') do |string|
|
71
|
+
@stdout = `#{string}`
|
76
72
|
@exitstatus = $CHILD_STATUS.exitstatus
|
77
73
|
end
|
78
74
|
|
@@ -81,7 +77,7 @@ When(/^I run bash with:$/) do |text|
|
|
81
77
|
@exitstatus = $CHILD_STATUS.exitstatus
|
82
78
|
end
|
83
79
|
|
84
|
-
When(
|
80
|
+
When('I copy this gem into temp dir') do
|
85
81
|
FileUtils.copy_entry(@cwd, File.join(@dir, 'jekyll-chatgpt-translate'))
|
86
82
|
end
|
87
83
|
|
@@ -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.
|
31
|
+
s.version = '0.0.19'
|
32
32
|
s.license = 'MIT'
|
33
33
|
s.summary = 'Translate Jekyll Pages Through ChatGPT'
|
34
34
|
s.description = [
|
@@ -47,12 +47,12 @@ class GptTranslate::ChatGPT
|
|
47
47
|
@target = target
|
48
48
|
end
|
49
49
|
|
50
|
-
def translate(text)
|
50
|
+
def translate(text, min: 32)
|
51
51
|
text.split("\n\n").compact.map do |par|
|
52
|
-
if par.length
|
52
|
+
if par.length < min
|
53
53
|
Jekyll.logger.debug("Not translating this, b/c too short: \"#{par}\"")
|
54
54
|
par
|
55
|
-
elsif par !~ /^[[:alpha:]]/
|
55
|
+
elsif par !~ /^[[[:alpha:]]'"]/
|
56
56
|
Jekyll.logger.debug("Not translating this, b/c it's not a plain text: \"#{par}\"")
|
57
57
|
par
|
58
58
|
elsif @key.empty?
|
@@ -53,6 +53,7 @@ class GptTranslate::Generator < Jekyll::Generator
|
|
53
53
|
layout = config['layout'] || 'translated'
|
54
54
|
version = config['version'] || GptTranslate::VERSION
|
55
55
|
threshold = config['threshold'] || 1024
|
56
|
+
min_chars = config['min_chars'] || 128
|
56
57
|
start = Time.now
|
57
58
|
translated = 0
|
58
59
|
copied = 0
|
@@ -68,41 +69,42 @@ class GptTranslate::Generator < Jekyll::Generator
|
|
68
69
|
FileUtils.mkdir_p(File.dirname(path))
|
69
70
|
File.write(path, '') # in order to surpress warnings in Page ctor
|
70
71
|
dest = Jekyll::Page.new(site, site.source, File.dirname(path), File.basename(path)).destination(site.dest)
|
71
|
-
|
72
|
-
doc.data['chatgpt-model'] = model
|
73
|
-
if GptTranslate::Ping.new(site, link).found?(dest, version)
|
72
|
+
if config['no_download'].nil? && GptTranslate::Ping.new(site, link).found?(dest, version)
|
74
73
|
copied += 1
|
74
|
+
elsif translated >= threshold
|
75
75
|
next
|
76
|
+
else
|
77
|
+
gpt = GptTranslate::ChatGPT.new(
|
78
|
+
key,
|
79
|
+
model,
|
80
|
+
config['source'] || 'en',
|
81
|
+
lang
|
82
|
+
)
|
83
|
+
foreign = gpt.translate(plain, min: min_chars)
|
84
|
+
File.write(
|
85
|
+
path,
|
86
|
+
[
|
87
|
+
'---',
|
88
|
+
"layout: #{target['layout'] || layout}",
|
89
|
+
"title: #{doc['title'].to_json}",
|
90
|
+
"description: #{doc['description'].to_json}",
|
91
|
+
"permalink: #{link.to_json}",
|
92
|
+
"translated-original-url: #{doc.url.to_json}",
|
93
|
+
"translated-language: #{lang.to_json}",
|
94
|
+
"chatgpt-model: #{model.to_json}",
|
95
|
+
'---',
|
96
|
+
'',
|
97
|
+
foreign,
|
98
|
+
'',
|
99
|
+
"#{marker} on #{Time.now.strftime('%Y-%m-%d at %H:%M')}\n{: .jekyll-chatgpt-translate}"
|
100
|
+
].join("\n")
|
101
|
+
)
|
102
|
+
site.pages << Jekyll::Page.new(site, site.source, File.dirname(path), File.basename(path))
|
103
|
+
translated += 1
|
104
|
+
Jekyll.logger.info("Translated via ChatGPT: #{path} (#{File.size(path)} bytes)")
|
76
105
|
end
|
77
|
-
|
78
|
-
|
79
|
-
key,
|
80
|
-
model,
|
81
|
-
config['source'] || 'en',
|
82
|
-
lang
|
83
|
-
)
|
84
|
-
foreign = gpt.translate(plain)
|
85
|
-
File.write(
|
86
|
-
path,
|
87
|
-
[
|
88
|
-
'---',
|
89
|
-
"layout: #{target['layout'] || layout}",
|
90
|
-
"title: #{doc['title'].to_json}",
|
91
|
-
"description: #{doc['description'].to_json}",
|
92
|
-
"permalink: #{link.to_json}",
|
93
|
-
"translated-original-url: #{doc.url.to_json}",
|
94
|
-
"translated-language: #{lang.to_json}",
|
95
|
-
"chatgpt-model: #{model.to_json}",
|
96
|
-
'---',
|
97
|
-
'',
|
98
|
-
foreign,
|
99
|
-
'',
|
100
|
-
"#{marker} on #{Time.now.strftime('%d/%m/%Y %H:%M')}\n{: .jekyll-chatgpt-translate}"
|
101
|
-
].join("\n")
|
102
|
-
)
|
103
|
-
site.pages << Jekyll::Page.new(site, site.source, File.dirname(path), File.basename(path))
|
104
|
-
translated += 1
|
105
|
-
Jekyll.logger.info("Translated via ChatGPT: #{path} (#{File.size(path)} bytes)")
|
106
|
+
doc.data["translated-#{lang}-url"] = link
|
107
|
+
doc.data['chatgpt-model'] = model
|
106
108
|
end
|
107
109
|
end
|
108
110
|
Jekyll.logger.info("#{translated} pages translated and #{copied} pages copied in #{(Time.now - start).round(2)}s")
|
@@ -39,7 +39,7 @@ class GptTranslate::Plain
|
|
39
39
|
|
40
40
|
def to_s
|
41
41
|
# To turn compact lists into proper lists
|
42
|
-
@markdown.gsub(/([^\n])\n(\s*\*)/, "\\1\n\n\\2").split(/\n{2,}/).compact.map do |par|
|
42
|
+
@markdown.gsub(/([^\n])\n(\s*\* )/, "\\1\n\n\\2").split(/\n{2,}/).compact.map do |par|
|
43
43
|
par.strip!
|
44
44
|
# Liquid tags are removed, but this implementation is primitive
|
45
45
|
# Seehttps://stackoverflow.com/questions/
|
@@ -55,6 +55,7 @@ class GptTranslate::Plain
|
|
55
55
|
end
|
56
56
|
|
57
57
|
# Markdown to pain text.
|
58
|
+
# Motivated by https://github.com/vmg/redcarpet/blob/master/lib/redcarpet/render_strip.rb
|
58
59
|
class Strip < Redcarpet::Render::Base
|
59
60
|
%i[
|
60
61
|
block_code block_quote
|
@@ -71,6 +72,10 @@ class GptTranslate::Plain
|
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
75
|
+
def header(text, level)
|
76
|
+
"#{'#' * level} #{text}"
|
77
|
+
end
|
78
|
+
|
74
79
|
def codespan(content)
|
75
80
|
if content.start_with?("\n")
|
76
81
|
"```#{content}```"
|
@@ -81,6 +86,10 @@ class GptTranslate::Plain
|
|
81
86
|
end
|
82
87
|
end
|
83
88
|
|
89
|
+
def image(link, title, alt)
|
90
|
+
""
|
91
|
+
end
|
92
|
+
|
84
93
|
def raw_html(content)
|
85
94
|
content
|
86
95
|
end
|
data/test/test_generator.rb
CHANGED
@@ -75,28 +75,23 @@ class GptTranslate::GeneratorTest < Minitest::Test
|
|
75
75
|
end
|
76
76
|
|
77
77
|
class FakeDocument
|
78
|
+
attr_reader :data
|
79
|
+
|
78
80
|
def initialize(path)
|
79
81
|
@path = path
|
82
|
+
@data = { 'date' => Time.now, 'title' => 'Hello!' }
|
80
83
|
end
|
81
84
|
|
82
85
|
def content
|
83
86
|
'Hello, world!'
|
84
87
|
end
|
85
88
|
|
86
|
-
def
|
87
|
-
|
89
|
+
def []=(key, value)
|
90
|
+
@data[key] = value
|
88
91
|
end
|
89
92
|
|
90
|
-
def []=(key, value); end
|
91
|
-
|
92
93
|
def [](key)
|
93
|
-
|
94
|
-
Time.now
|
95
|
-
elsif key == 'title'
|
96
|
-
'Hello!'
|
97
|
-
else
|
98
|
-
''
|
99
|
-
end
|
94
|
+
@data[key] || ''
|
100
95
|
end
|
101
96
|
|
102
97
|
def relative_path
|
data/test/test_plain.rb
CHANGED
@@ -31,8 +31,10 @@ require_relative '../lib/jekyll-chatgpt-translate/plain'
|
|
31
31
|
# License:: MIT
|
32
32
|
class GptTranslate::PlainTest < Minitest::Test
|
33
33
|
def test_simple_map
|
34
|
-
assert_equal('Hello, world!', GptTranslate::Plain.new(
|
34
|
+
assert_equal('Hello, world!', GptTranslate::Plain.new("Hello,\n**world**!").to_s)
|
35
|
+
assert_equal('Hello, world!', GptTranslate::Plain.new("Hello,\n[world](/x.html)!").to_s)
|
35
36
|
assert_equal('Hello, Jeff!', GptTranslate::Plain.new('Hello, _Jeff_!').to_s)
|
37
|
+
# assert_equal('Hello, Walter!', GptTranslate::Plain.new('Hello, ~Walter~!').to_s)
|
36
38
|
assert_equal("Hi\n\nBye", GptTranslate::Plain.new(" Hi\n\nBye\n\n\n").to_s)
|
37
39
|
assert_equal('Hi, dude!', GptTranslate::Plain.new(" Hi,\ndude!\n").to_s)
|
38
40
|
end
|
@@ -83,6 +85,16 @@ class GptTranslate::PlainTest < Minitest::Test
|
|
83
85
|
)
|
84
86
|
end
|
85
87
|
|
88
|
+
def test_titles
|
89
|
+
assert_equal('# Hello', GptTranslate::Plain.new('# Hello').to_s)
|
90
|
+
assert_equal('## Hello', GptTranslate::Plain.new('## Hello').to_s)
|
91
|
+
assert_equal('### Hello', GptTranslate::Plain.new('### Hello').to_s)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_image
|
95
|
+
assert_equal('', GptTranslate::Plain.new('').to_s)
|
96
|
+
end
|
97
|
+
|
86
98
|
def test_html
|
87
99
|
assert_equal(
|
88
100
|
'This is picture: <img src="a"/>!',
|