jekyll-chatgpt-translate 0.0.13 → 0.0.15

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: 864696015c8e2b7ee1abba3e5bd8aee3310d7d9d3d85721b5a082b45eef6cd0b
4
- data.tar.gz: cfc8b8d09865af57aea8202be714c0ee7211da0fc2121873b8004f37cf40a507
3
+ metadata.gz: 0104da23aeb28e61fb3c2eb4599684accff5945175001b86a49cc821f5e49be6
4
+ data.tar.gz: 05a05b676a664ec01567f15c49c24bbc2809bd3aeb4dd11666eeea123ec19a7e
5
5
  SHA512:
6
- metadata.gz: 83cbb3ae370b246351ce64302e48b0d5c4b94fcc985fb7c239f36f7c2767e5779fa45998ae6b808b8c8e973369ee6d6f21c9a62b241cb5459fb235eb9a424d01
7
- data.tar.gz: 9400ee361c82cf27582e416a607d292f16850269fa204a837ff40f052917692dbb0a8d9f3aade9d21d0c2d74870028d6c8c4aec50b4b0efd177f6efc6a220e5c
6
+ metadata.gz: f9e400ffbf49216617b0a10cf6600a8786c891dbb73d950da2bdd363acf2c67e1d8e3e86c119a26be56aaed2226bd3b64d1dfb136c7b9272ac4e993ec7c83e81
7
+ data.tar.gz: 1b4d7a1da595f9bf4829b739d786268c66bac31d9b3b42d9cd9a422bcb1b626af9aa54eeb0088be7e33c2fe39aaa787e972d6c136df20769e55f39f290d6285d
data/.gitignore CHANGED
@@ -2,4 +2,5 @@ Gemfile.lock
2
2
  *.gem
3
3
  .bundle/
4
4
  .DS_Store
5
- coverage/
5
+ coverage/
6
+ _chatgpt-translated/
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
- Then File "_chatgpt-translated/cn/2023-01-01-hello-cn.md" exists
44
- Then File "_site/2023/01/01/hello.html" exists
45
- Then File "_site/2023/01/01/hello.html" contains "The Chinese: /2023-01-01-hello-chinese.html"
46
- Then File "_site/2023-01-01-hello-chinese.html" exists
47
- Then File "_site/2023-01-01-hello-chinese.html" contains "The original: /2023/01/01/hello.html"
48
- Then File "_site/2023/hello-french.html" exists
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.13'
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
- t = nil
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
- t = response.dig('choices', 0, 'message', 'content')
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 #{t.split.count} #{@target.upcase} words \
89
+ to #{answer.split.count} #{@target.upcase} words \
90
90
  through #{@model} in #{(Time.now - start).round(2)}s")
91
- t
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.data['title']}",
85
- "permalink: #{link}",
86
- "translated-original-url: #{doc.url}",
87
- "chatgpt-model: #{model}",
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
- #{uri} (#{html.split.count} words), saved to #{file}")
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.info("Failed to ping \"#{uri}\": #{e.message}")
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
- @markdown.split(/\n{2,}/).compact.map do |par|
42
- par.gsub!("\n", ' ')
43
- par.gsub!(/\s{2,}/, ' ')
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
- def method_missing(*)
56
- nil
57
- end
56
+ # # To ignore/remove Liquid tags.
57
+ # class NullDrop < Liquid::Drop
58
+ # def method_missing(*)
59
+ # nil
60
+ # end
58
61
 
59
- def respond_to_missing?(*)
60
- true
61
- end
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
@@ -23,5 +23,5 @@
23
23
  # SOFTWARE.
24
24
 
25
25
  module GptTranslate
26
- VERSION = '0.0.13'
26
+ VERSION = '0.0.15'
27
27
  end
@@ -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
- # assert(stdout.include?('DEBUG'))
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
@@ -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.13
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