jekyll-chatgpt-translate 0.0.13 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/features/cli.feature +7 -6
- data/features/step_definitions/steps.rb +2 -1
- data/jekyll-chatgpt-translate.gemspec +1 -1
- data/lib/jekyll-chatgpt-translate/chatgpt.rb +8 -23
- data/lib/jekyll-chatgpt-translate/generator.rb +14 -10
- data/lib/jekyll-chatgpt-translate/ping.rb +3 -2
- data/lib/jekyll-chatgpt-translate/plain.rb +16 -13
- data/lib/jekyll-chatgpt-translate/prompt.rb +59 -0
- data/lib/jekyll-chatgpt-translate/version.rb +1 -1
- data/test/test_generator.rb +119 -1
- data/test/test_plain.rb +30 -0
- data/test/test_prompt.rb +50 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0104da23aeb28e61fb3c2eb4599684accff5945175001b86a49cc821f5e49be6
|
4
|
+
data.tar.gz: 05a05b676a664ec01567f15c49c24bbc2809bd3aeb4dd11666eeea123ec19a7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9e400ffbf49216617b0a10cf6600a8786c891dbb73d950da2bdd363acf2c67e1d8e3e86c119a26be56aaed2226bd3b64d1dfb136c7b9272ac4e993ec7c83e81
|
7
|
+
data.tar.gz: 1b4d7a1da595f9bf4829b739d786268c66bac31d9b3b42d9cd9a422bcb1b626af9aa54eeb0088be7e33c2fe39aaa787e972d6c136df20769e55f39f290d6285d
|
data/.gitignore
CHANGED
data/features/cli.feature
CHANGED
@@ -40,11 +40,12 @@ Feature: Simple site building
|
|
40
40
|
Hello, world!
|
41
41
|
"""
|
42
42
|
Then I build Jekyll site
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
And File "_chatgpt-translated/cn/2023-01-01-hello-cn.md" exists
|
44
|
+
And File "_chatgpt-translated/cn/2023-01-01-hello-cn.md" contains "/2023-01-01-hello-chinese.html"
|
45
|
+
And File "_site/2023/01/01/hello.html" exists
|
46
|
+
And File "_site/2023/01/01/hello.html" contains "The Chinese: /2023-01-01-hello-chinese.html"
|
47
|
+
And File "_site/2023-01-01-hello-chinese.html" exists
|
48
|
+
And File "_site/2023-01-01-hello-chinese.html" contains "The original: /2023/01/01/hello.html"
|
49
|
+
And File "_site/2023/hello-french.html" exists
|
49
50
|
And Exit code is zero
|
50
51
|
|
@@ -50,10 +50,11 @@ Then(/^Stdout contains "([^"]*)"$/) do |txt|
|
|
50
50
|
end
|
51
51
|
|
52
52
|
Then(/^File "([^"]*)" exists$/) do |name|
|
53
|
-
raise "The file \"#{name}\" is absent:\n#{`tree`}" unless File.exist?(name)
|
53
|
+
raise "The file \"#{name}\" is absent:\n#{`tree -s`}" unless File.exist?(name)
|
54
54
|
end
|
55
55
|
|
56
56
|
Then(/^File "([^"]*)" contains "([^"]*)"$/) do |name, text|
|
57
|
+
raise "The file \"#{name}\" is absent" unless File.exist?(name)
|
57
58
|
content = File.read(name)
|
58
59
|
raise "The file \"#{name}\" doesn't contain \"#{text}\":\n#{content}" unless content.include?(text)
|
59
60
|
end
|
@@ -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.15'
|
32
32
|
s.license = 'MIT'
|
33
33
|
s.summary = 'Translate Jekyll Pages Through ChatGPT'
|
34
34
|
s.description = [
|
@@ -25,6 +25,7 @@
|
|
25
25
|
require 'jekyll'
|
26
26
|
require 'openai'
|
27
27
|
require 'iso-639'
|
28
|
+
require_relative 'prompt'
|
28
29
|
|
29
30
|
# The module we are in.
|
30
31
|
module GptTranslate; end
|
@@ -66,43 +67,27 @@ class GptTranslate::ChatGPT
|
|
66
67
|
|
67
68
|
def translate_par(par)
|
68
69
|
start = Time.now
|
69
|
-
|
70
|
+
answer = nil
|
70
71
|
attempt = 0
|
71
72
|
begin
|
73
|
+
prompt = GptTranslate::Prompt.new(par, @source, @target).to_s
|
72
74
|
response = OpenAI::Client.new(access_token: @key).chat(
|
73
75
|
parameters: {
|
74
76
|
model: @model,
|
75
|
-
messages: [{
|
76
|
-
role: 'user',
|
77
|
-
content: "#{prompt}:\n\n#{par}"
|
78
|
-
}],
|
77
|
+
messages: [{ role: 'user', content: prompt }],
|
79
78
|
temperature: 0.7
|
80
79
|
}
|
81
80
|
)
|
82
|
-
|
81
|
+
answer = response.dig('choices', 0, 'message', 'content')
|
82
|
+
Jekyll.logger.debug("ChatGPT prompt: \"#{prompt}\", ChatGPT answer: \"#{answer}\"")
|
83
83
|
rescue StandardError => e
|
84
84
|
attempt += 1
|
85
85
|
retry if attempt < 4
|
86
86
|
raise e
|
87
87
|
end
|
88
88
|
Jekyll.logger.info("Translated #{par.split.count} #{@source.upcase} words \
|
89
|
-
to #{
|
89
|
+
to #{answer.split.count} #{@target.upcase} words \
|
90
90
|
through #{@model} in #{(Time.now - start).round(2)}s")
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
def prompt
|
95
|
-
if (@source == 'ru') && (@target == 'en')
|
96
|
-
'Пожалуйста, переведи этот параграф на английский язык'
|
97
|
-
elsif (@source == 'en') && (@target == 'ru')
|
98
|
-
'Please, translate this paragraph to Russian'
|
99
|
-
else
|
100
|
-
[
|
101
|
-
'Please, translate this paragraph from',
|
102
|
-
ISO_639.find_by_code(@source),
|
103
|
-
'to',
|
104
|
-
ISO_639.find_by_code(@target)
|
105
|
-
].join(' ')
|
106
|
-
end
|
91
|
+
answer
|
107
92
|
end
|
108
93
|
end
|
@@ -23,6 +23,7 @@
|
|
23
23
|
# SOFTWARE.
|
24
24
|
|
25
25
|
require 'jekyll'
|
26
|
+
require 'json'
|
26
27
|
require_relative 'chatgpt'
|
27
28
|
require_relative 'permalink'
|
28
29
|
require_relative 'ping'
|
@@ -60,13 +61,19 @@ class GptTranslate::Generator < Jekyll::Generator
|
|
60
61
|
plain = GptTranslate::Plain.new(doc.content).to_s
|
61
62
|
config['targets'].each do |target|
|
62
63
|
link = GptTranslate::Permalink.new(doc, target['permalink']).to_path
|
63
|
-
next if GptTranslate::Ping.new(site, link).found?(doc.path, version)
|
64
64
|
lang = target['language']
|
65
65
|
raise 'Language must be defined for each target' if target.nil?
|
66
66
|
if total >= threshold
|
67
67
|
Jekyll.logger.info("Already generated #{total} pages, that's enough for today")
|
68
68
|
break
|
69
69
|
end
|
70
|
+
path = File.join(home, lang, doc.basename.gsub(/\.md$/, "-#{lang}.md"))
|
71
|
+
FileUtils.mkdir_p(File.dirname(path))
|
72
|
+
File.write(path, '') # in order to surpress warnings in Page ctor
|
73
|
+
dest = Jekyll::Page.new(site, site.source, File.dirname(path), File.basename(path)).destination(site.dest)
|
74
|
+
doc.data["translated-#{lang}-url"] = link
|
75
|
+
doc.data['chatgpt-model'] = model
|
76
|
+
next if GptTranslate::Ping.new(site, link).found?(dest, version)
|
70
77
|
gpt = GptTranslate::ChatGPT.new(
|
71
78
|
key,
|
72
79
|
model,
|
@@ -74,26 +81,23 @@ class GptTranslate::Generator < Jekyll::Generator
|
|
74
81
|
lang
|
75
82
|
)
|
76
83
|
translated = gpt.translate(plain)
|
77
|
-
path = File.join(home, lang, doc.basename.gsub(/\.md$/, "-#{lang}.md"))
|
78
|
-
FileUtils.mkdir_p(File.dirname(path))
|
79
84
|
File.write(
|
80
85
|
path,
|
81
86
|
[
|
82
87
|
'---',
|
83
88
|
"layout: #{target['layout'] || layout}",
|
84
|
-
"title: #{doc
|
85
|
-
"
|
86
|
-
"
|
87
|
-
"
|
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
|
+
"chatgpt-model: #{model.to_json}",
|
88
94
|
'---',
|
89
95
|
'',
|
90
96
|
translated,
|
91
97
|
'',
|
92
|
-
"#{marker}\n{: .jekyll-chatgpt-translate}"
|
98
|
+
"#{marker} on #{Time.now.strftime('%d/%m/%Y %H:%M')}\n{: .jekyll-chatgpt-translate}"
|
93
99
|
].join("\n")
|
94
100
|
)
|
95
|
-
doc.data["translated-#{lang}-url"] = link
|
96
|
-
doc.data['chatgpt-model'] = model
|
97
101
|
site.pages << Jekyll::Page.new(site, site.source, File.dirname(path), File.basename(path))
|
98
102
|
total += 1
|
99
103
|
Jekyll.logger.info("Translated via ChatGPT: #{path}")
|
@@ -57,7 +57,7 @@ class GptTranslate::Ping
|
|
57
57
|
html = before.body
|
58
58
|
if html.include?(marker)
|
59
59
|
Jekyll.logger.info("No need to translate, the page exists at \
|
60
|
-
|
60
|
+
\"#{uri}\" (#{html.split.count} words), saved to \"#{file}\"")
|
61
61
|
FileUtils.mkdir_p(File.dirname(file))
|
62
62
|
File.write(file, html)
|
63
63
|
return true
|
@@ -68,7 +68,8 @@ class GptTranslate::Ping
|
|
68
68
|
end
|
69
69
|
Jekyll.logger.debug("GET \"#{uri}\": #{before.code}")
|
70
70
|
rescue StandardError => e
|
71
|
-
Jekyll.logger.
|
71
|
+
Jekyll.logger.debug("Failed to ping \"#{uri}\": #{e.message}")
|
72
|
+
Jekyll.logger.info("The page is absent: \"#{uri}\"")
|
72
73
|
end
|
73
74
|
false
|
74
75
|
end
|
@@ -38,28 +38,31 @@ class GptTranslate::Plain
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def to_s
|
41
|
-
|
42
|
-
|
43
|
-
par.gsub!(
|
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|
|
43
|
+
par.gsub!("\t", ' ')
|
44
|
+
par.gsub!(/\n+/, ' ')
|
45
|
+
par.gsub!(/ {2,}/, ' ')
|
44
46
|
# Liquid tags are removed, but this implementation is primitive
|
45
47
|
# Seehttps://stackoverflow.com/questions/
|
46
48
|
par.gsub!(/{{[^}]+}}/, '')
|
47
|
-
par.gsub!(/{
|
49
|
+
par.gsub!(/{%.+?%}/, '')
|
50
|
+
par.gsub!(/<!--.+?-->/m, '')
|
48
51
|
par.strip!
|
49
52
|
Redcarpet::Markdown.new(Strip).render(par)
|
50
53
|
end.join("\n\n").gsub(/\n{2,}/, "\n\n").strip
|
51
54
|
end
|
52
55
|
|
53
|
-
# To ignore/remove Liquid tags.
|
54
|
-
class NullDrop < Liquid::Drop
|
55
|
-
|
56
|
-
|
57
|
-
|
56
|
+
# # To ignore/remove Liquid tags.
|
57
|
+
# class NullDrop < Liquid::Drop
|
58
|
+
# def method_missing(*)
|
59
|
+
# nil
|
60
|
+
# end
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
62
|
+
# def respond_to_missing?(*)
|
63
|
+
# true
|
64
|
+
# end
|
65
|
+
# end
|
63
66
|
|
64
67
|
# Markdown to pain text.
|
65
68
|
class Strip < Redcarpet::Render::Base
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (The MIT License)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023 Yegor Bugayenko
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
|
25
|
+
require 'iso-639'
|
26
|
+
|
27
|
+
# The module we are in.
|
28
|
+
module GptTranslate; end
|
29
|
+
|
30
|
+
# Prompt for ChatGPT.
|
31
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
32
|
+
# Copyright:: Copyright (c) 2023 Yegor Bugayenko
|
33
|
+
# License:: MIT
|
34
|
+
class GptTranslate::Prompt
|
35
|
+
# Ctor.
|
36
|
+
# +par+ Text to translate
|
37
|
+
# +source+ The language to translate from
|
38
|
+
# +target+ The language to translate into
|
39
|
+
def initialize(par, source, target)
|
40
|
+
@par = par
|
41
|
+
@source = source
|
42
|
+
@target = target
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
from = ISO_639.find_by_code(@source)
|
47
|
+
raise "Unknown source language ISO-639 code: \"#{@source}\"" if from.nil?
|
48
|
+
to = ISO_639.find_by_code(@target)
|
49
|
+
raise "Unknown source language ISO-639 code: \"#{@target}\"" if to.nil?
|
50
|
+
head = [
|
51
|
+
'Please, translate the following paragraph from ',
|
52
|
+
from[3],
|
53
|
+
' to ',
|
54
|
+
to[3],
|
55
|
+
', don\'t change proper nouns'
|
56
|
+
].join
|
57
|
+
"#{head}:\n\n#{@par}"
|
58
|
+
end
|
59
|
+
end
|
data/test/test_generator.rb
CHANGED
@@ -23,6 +23,8 @@
|
|
23
23
|
# SOFTWARE.
|
24
24
|
|
25
25
|
require 'minitest/autorun'
|
26
|
+
require 'tmpdir'
|
27
|
+
require 'webmock/minitest'
|
26
28
|
require_relative '../lib/jekyll-chatgpt-translate/generator'
|
27
29
|
|
28
30
|
# Generator test.
|
@@ -30,7 +32,123 @@ require_relative '../lib/jekyll-chatgpt-translate/generator'
|
|
30
32
|
# Copyright:: Copyright (c) 2023 Yegor Bugayenko
|
31
33
|
# License:: MIT
|
32
34
|
class GptTranslate::GeneratorTest < Minitest::Test
|
35
|
+
class FakeSite
|
36
|
+
attr_reader :config
|
37
|
+
|
38
|
+
def initialize(config, doc)
|
39
|
+
@config = config
|
40
|
+
@doc = doc
|
41
|
+
end
|
42
|
+
|
43
|
+
def posts
|
44
|
+
FakePosts.new(@doc)
|
45
|
+
end
|
46
|
+
|
47
|
+
def pages
|
48
|
+
[]
|
49
|
+
end
|
50
|
+
|
51
|
+
def permalink_style
|
52
|
+
''
|
53
|
+
end
|
54
|
+
|
55
|
+
def frontmatter_defaults
|
56
|
+
Jekyll::FrontmatterDefaults.new(self)
|
57
|
+
end
|
58
|
+
|
59
|
+
def converters
|
60
|
+
[Jekyll::Converters::Markdown.new({ 'markdown_ext' => 'md' })]
|
61
|
+
end
|
62
|
+
|
63
|
+
def source
|
64
|
+
''
|
65
|
+
end
|
66
|
+
|
67
|
+
def dest
|
68
|
+
''
|
69
|
+
end
|
70
|
+
|
71
|
+
def in_theme_dir(base, _foo = nil, _bar = nil)
|
72
|
+
base
|
73
|
+
end
|
74
|
+
|
75
|
+
def in_dest_dir(*paths)
|
76
|
+
paths[0].dup
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class FakeDocument
|
81
|
+
def initialize(path)
|
82
|
+
@path = path
|
83
|
+
end
|
84
|
+
|
85
|
+
def content
|
86
|
+
'Hello, world!'
|
87
|
+
end
|
88
|
+
|
89
|
+
def data
|
90
|
+
{}
|
91
|
+
end
|
92
|
+
|
93
|
+
def []=(key, value); end
|
94
|
+
|
95
|
+
def [](key)
|
96
|
+
if key == 'date'
|
97
|
+
Time.now
|
98
|
+
elsif key == 'title'
|
99
|
+
'Hello!'
|
100
|
+
else
|
101
|
+
''
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def relative_path
|
106
|
+
@path
|
107
|
+
end
|
108
|
+
|
109
|
+
def url
|
110
|
+
'2023-01-01-hello.html'
|
111
|
+
end
|
112
|
+
|
113
|
+
def basename
|
114
|
+
'2023-01-01-hello.md'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class FakePosts
|
119
|
+
attr_reader :config
|
120
|
+
|
121
|
+
def initialize(doc)
|
122
|
+
@doc = doc
|
123
|
+
end
|
124
|
+
|
125
|
+
def docs
|
126
|
+
[FakeDocument.new(@doc)]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
33
130
|
def test_simple_scenario
|
34
|
-
|
131
|
+
Dir.mktmpdir do |home|
|
132
|
+
post = File.join(home, '2023-01-01-hello.md')
|
133
|
+
File.write(post, "---\ntitle: Hello\n---\n\nHello, world!")
|
134
|
+
site = FakeSite.new(
|
135
|
+
{
|
136
|
+
'url' => 'https://www.yegor256.com/',
|
137
|
+
'chatgpt-translate' => {
|
138
|
+
'targets' => [
|
139
|
+
{
|
140
|
+
'language' => 'cn',
|
141
|
+
'layout' => 'chinese',
|
142
|
+
'permalink' => ':slug.html'
|
143
|
+
}
|
144
|
+
]
|
145
|
+
}
|
146
|
+
},
|
147
|
+
FakeDocument.new({})
|
148
|
+
)
|
149
|
+
gen = GptTranslate::Generator.new
|
150
|
+
stub_request(:get, 'https://www.yegor256.com/.html').to_return(body: '')
|
151
|
+
gen.generate(site)
|
152
|
+
end
|
35
153
|
end
|
36
154
|
end
|
data/test/test_plain.rb
CHANGED
@@ -34,6 +34,7 @@ class GptTranslate::PlainTest < Minitest::Test
|
|
34
34
|
assert_equal('Hello, world!', GptTranslate::Plain.new('Hello, **world**!').to_s)
|
35
35
|
assert_equal('Hello, Jeff!', GptTranslate::Plain.new('Hello, _Jeff_!').to_s)
|
36
36
|
assert_equal("Hi\n\nBye", GptTranslate::Plain.new(" Hi\n\nBye\n\n\n").to_s)
|
37
|
+
assert_equal('Hi, dude!', GptTranslate::Plain.new(" Hi,\ndude!\n").to_s)
|
37
38
|
end
|
38
39
|
|
39
40
|
def test_lists
|
@@ -47,6 +48,20 @@ class GptTranslate::PlainTest < Minitest::Test
|
|
47
48
|
)
|
48
49
|
end
|
49
50
|
|
51
|
+
def test_ordered_list
|
52
|
+
assert_equal(
|
53
|
+
"first\n\nsecond\n\nthird",
|
54
|
+
GptTranslate::Plain.new("1. first\n\n2. second\n\n3. third").to_s
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_compact_list
|
59
|
+
assert_equal(
|
60
|
+
"first\n\nsecond\n\nthird",
|
61
|
+
GptTranslate::Plain.new("* first\n* second\n* third").to_s
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
50
65
|
def test_links
|
51
66
|
assert_equal(
|
52
67
|
'Hello, dude!',
|
@@ -89,5 +104,20 @@ class GptTranslate::PlainTest < Minitest::Test
|
|
89
104
|
'Hello, !',
|
90
105
|
GptTranslate::Plain.new('Hello, {% Java %}!').to_s
|
91
106
|
)
|
107
|
+
assert_equal(
|
108
|
+
'Hello, !',
|
109
|
+
GptTranslate::Plain.new('Hello, {% plantuml "width=50%" %}!').to_s
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_html_comments
|
114
|
+
assert_equal(
|
115
|
+
'Hello, !',
|
116
|
+
GptTranslate::Plain.new('Hello, <!-- Java -->!').to_s
|
117
|
+
)
|
118
|
+
assert_equal(
|
119
|
+
'Hello, !',
|
120
|
+
GptTranslate::Plain.new("Hello, <!-- \nJava\n -->!").to_s
|
121
|
+
)
|
92
122
|
end
|
93
123
|
end
|
data/test/test_prompt.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (The MIT License)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023 Yegor Bugayenko
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
|
25
|
+
require 'minitest/autorun'
|
26
|
+
require_relative '../lib/jekyll-chatgpt-translate/prompt'
|
27
|
+
|
28
|
+
# Prompt test.
|
29
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
30
|
+
# Copyright:: Copyright (c) 2023 Yegor Bugayenko
|
31
|
+
# License:: MIT
|
32
|
+
class GptTranslate::PromptTest < Minitest::Test
|
33
|
+
def par(body, source, target)
|
34
|
+
"Please, translate the following paragraph from #{source} to #{target}, don't change proper nouns:\n\n#{body}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_english_to_russian
|
38
|
+
assert_equal(
|
39
|
+
par('Hello, dude!', 'English', 'Russian'),
|
40
|
+
GptTranslate::Prompt.new('Hello, dude!', 'en', 'ru').to_s
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_english_to_chinese
|
45
|
+
assert_equal(
|
46
|
+
par('Hello, Jeff!', 'English', 'Chinese'),
|
47
|
+
GptTranslate::Prompt.new('Hello, Jeff!', 'en', 'zh').to_s
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
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.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- lib/jekyll-chatgpt-translate/permalink.rb
|
111
111
|
- lib/jekyll-chatgpt-translate/ping.rb
|
112
112
|
- lib/jekyll-chatgpt-translate/plain.rb
|
113
|
+
- lib/jekyll-chatgpt-translate/prompt.rb
|
113
114
|
- lib/jekyll-chatgpt-translate/version.rb
|
114
115
|
- logo.png
|
115
116
|
- renovate.json
|
@@ -119,6 +120,7 @@ files:
|
|
119
120
|
- test/test_permalink.rb
|
120
121
|
- test/test_ping.rb
|
121
122
|
- test/test_plain.rb
|
123
|
+
- test/test_prompt.rb
|
122
124
|
homepage: https://github.com/yegor256/jekyll-chatgpt-translate
|
123
125
|
licenses:
|
124
126
|
- MIT
|