jekyll_plugin_template 0.1.3 → 0.3.0

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: 589cb215e8458e084b40967bd4b4360c457bb65a3fd01c9830af52a17d5c3bab
4
- data.tar.gz: 323ea35b37a006144ccb10227bff0f49a048a098670f79ee51dda4df4787fb4b
3
+ metadata.gz: a4c4b04f631f93d694b6ac414c7c13e9ee040bdb054adad7d8fcacf74c86d26d
4
+ data.tar.gz: 83990ea5e791dc5fddf63e9493ca50af1ecacbd35021481f1400b09df70b0cc1
5
5
  SHA512:
6
- metadata.gz: 3d0850c46f853f9925e99e92f423e1918303f4ae253b5f45bad8711e614d3cfc76824b7f369d0d6b7a82282440647fd1a9c6d4d5ac66b3605f56ca2d4f62cf41
7
- data.tar.gz: 59fdefd6d4baff1526db8065f2691b01c86a0d889d3aaed5f81ff75adb2ea83da5982b23198fa90a3e167815ff8285d8879841078ebac374ae673cc30f8fba37
6
+ metadata.gz: f37621435bcb0c4d22a3765deee2e2a8942a3c6e1198ad2f737076c8aa8898937bc32d1ce2b2573fdfc16390cf05be92de5701226355764ab086553c21b03024
7
+ data.tar.gz: 3968dcc9173c86d0466cd00fb5d67e5236e716136a237b6e03b9a3509a319a948f8c804e22b1d46d5021d8f43d82911c6f1c75e22008bbb883b16234acb834ad
data/.rubocop.yml CHANGED
@@ -1,35 +1,103 @@
1
- # require: rubocop-jekyll
2
- # inherit_gem:
3
- # rubocop-jekyll: .rubocop.yml
1
+ require:
2
+ # - rubocop-jekyll
3
+ - rubocop-md
4
+ - rubocop-performance
5
+ - rubocop-rake
6
+ - rubocop-rspec
4
7
 
5
8
  AllCops:
6
9
  Exclude:
7
- - vendor/**/*
8
- - Gemfile*
9
- - '*.gemspec' # This does nothing. Why?
10
+ - demo/_site/**/*
11
+ - exe/**/*
12
+ - vendor/**/*
13
+ - Gemfile*
14
+ - Rakefile
15
+ - jekyll_plugin_template.gemspec
10
16
  NewCops: enable
11
17
  TargetRubyVersion: 2.6
12
18
 
13
- # Gemspec/RequireMFA:
14
- # Enabled: false
19
+ Gemspec/DeprecatedAttributeAssignment:
20
+ Enabled: false
15
21
 
16
- # Jekyll/NoPutsAllowed:
17
- # Enabled: false
22
+ Gemspec/RequireMFA:
23
+ Enabled: false
24
+
25
+ Layout/InitialIndentation:
26
+ Exclude:
27
+ - README.md
18
28
 
19
29
  Layout/HashAlignment:
30
+ EnforcedColonStyle: table
20
31
  EnforcedHashRocketStyle: table
21
32
 
22
33
  Layout/LineLength:
23
34
  Max: 150
24
35
 
36
+ Layout/MultilineMethodCallIndentation:
37
+ Enabled: false
38
+
39
+ Lint/RedundantCopDisableDirective:
40
+ Exclude:
41
+ - jekyll_plugin_template.gemspec
42
+
43
+ Metrics/AbcSize:
44
+ Max: 35
45
+
25
46
  Metrics/BlockLength:
26
- Max: 50
47
+ Exclude:
48
+ - jekyll_plugin_template.gemspec
49
+ - spec/**/*
50
+
51
+ Metrics/ClassLength:
52
+ Exclude:
53
+ - spec/**/*
27
54
 
28
55
  Metrics/MethodLength:
29
56
  Max: 40
30
57
 
31
- Metrics/ModuleLength:
58
+ Metrics/CyclomaticComplexity:
59
+ Max: 10
60
+
61
+ Metrics/PerceivedComplexity:
62
+ Max: 10
63
+
64
+ Naming/FileName:
65
+ Exclude:
66
+ - Rakefile
67
+
68
+ RSpec/ExampleLength:
69
+ Max: 20
70
+
71
+ RSpec/MultipleExpectations:
72
+ Max: 15
73
+
74
+ Style/CommandLiteral:
75
+ Enabled: false
76
+
77
+ Style/CommentedKeyword:
78
+ Enabled: false
79
+
80
+ Style/Documentation:
81
+ Enabled: false
82
+
83
+ Style/FrozenStringLiteralComment:
84
+ Enabled: false
85
+
86
+ Style/PercentLiteralDelimiters:
87
+ Enabled: false
88
+
89
+ Style/RegexpLiteral:
32
90
  Enabled: false
33
91
 
92
+ Style/StringConcatenation:
93
+ Exclude:
94
+ - spec/**/*
95
+
34
96
  Style/StringLiterals:
35
97
  Enabled: false
98
+
99
+ Style/StringLiteralsInInterpolation:
100
+ Enabled: false
101
+
102
+ Style/TrailingCommaInHashLiteral:
103
+ EnforcedStyleForMultiline: comma
data/CHANGELOG.md CHANGED
@@ -1,6 +1,21 @@
1
+ ## 0.3.0 / 2023-04-05
2
+ * Updated to `jekyll_plugin_support` v0.6.0 for attribution support.
3
+ * Fixed `jeky_block_tag_plugin.rb` so it works properly with `jekyll_plugin_support`.
4
+
5
+ ## 0.2.0 / 2023-02-16
6
+ * Updated to `jekyll_plugin_support` v0.5.0.
7
+
8
+ ## 0.1.3 / 2023-02-12
9
+ * Added `grin`, `horns`, `open`, `poop` and `sad` emojis.
10
+ * Now based on [`JekyllSupport::JekyllTag`](https://mslinn.com/jekyll/10200-jekyll-plugin-support.html) instead of `Liquid::Tag`.
11
+ * Added `list` and `emoji_and_name` options.
12
+ * Updated `demo` to exercise the new features.
13
+ * `Demo` now builds the plugins prior to each run.
14
+
1
15
  ## 0.1.3 / 2022-04-15
2
16
  * Renamed `lib/jekyll_tag_plugins.rb` to `lib/jekyll_block_tag_plugin.rb`
3
17
  * Added `lib/jekyll_tag_plugin.rb`
18
+
4
19
  ## 0.1.2 / 2022-04-05
5
20
  * Initial version published
6
21
  * `bin/run_this_first` is unfinished but plugins work
data/Rakefile CHANGED
@@ -1,7 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
5
3
 
6
4
  RSpec::Core::RakeTask.new(:spec)
7
- task :default => :spec
5
+ task default: :spec
@@ -1,46 +1,39 @@
1
- # frozen_string_literal: true
1
+ require_relative 'lib/jekyll_plugin_template/version'
2
2
 
3
- require_relative "lib/jekyll_plugin_template/version"
3
+ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
4
+ github = 'https://github.com/mslinn/jekyll_plugin_template'
4
5
 
5
- Gem::Specification.new do |spec|
6
- github = "https://github.com/mslinn/jekyll_plugin_template"
7
-
8
- spec.authors = ["Firstname Lastname"]
9
- spec.bindir = "bin"
6
+ spec.authors = ['Firstname Lastname']
7
+ spec.bindir = 'bin'
10
8
  spec.description = <<~END_OF_DESC
11
9
  Expand on what spec.summary says.
12
10
  END_OF_DESC
13
- spec.email = ["email@email.com"]
11
+ spec.email = ['email@email.com']
14
12
  spec.executables = []
15
13
 
16
14
  # Specify which files should be added to the gem when it is released.
17
- spec.files = Dir[".rubocop.yml", "LICENSE.*", "Rakefile", "{lib,spec}/**/*", "*.gemspec", "*.md"]
15
+ spec.files = Dir['.rubocop.yml', 'LICENSE.*', 'Rakefile', '{lib,spec}/**/*', '*.gemspec', '*.md']
18
16
 
19
- spec.homepage = "https://www.mslinn.com/blog/2020/12/30/jekyll-plugin-template-collection.html"
20
- spec.license = "CC0-1.0"
17
+ spec.homepage = 'https://www.mslinn.com/jekyll/10400-jekyll-plugin-template-collection.html'
18
+ spec.license = 'CC0-1.0'
21
19
  spec.metadata = {
22
- "allowed_push_host" => "https://rubygems.org",
23
- "bug_tracker_uri" => "#{github}/issues",
24
- "changelog_uri" => "#{github}/CHANGELOG.md",
25
- "homepage_uri" => spec.homepage,
26
- "source_code_uri" => github,
20
+ 'allowed_push_host' => 'https://rubygems.org',
21
+ 'bug_tracker_uri' => "#{github}/issues",
22
+ 'changelog_uri' => "#{github}/CHANGELOG.md",
23
+ 'homepage_uri' => spec.homepage,
24
+ 'source_code_uri' => github,
27
25
  }
28
- spec.name = "jekyll_plugin_template"
29
- spec.require_paths = ["lib"]
30
- spec.required_ruby_version = ">= 2.6.0"
31
- spec.summary = "Write a short summary; RubyGems requires one."
26
+ spec.name = 'jekyll_plugin_template'
27
+ spec.require_paths = ['lib']
28
+ spec.required_ruby_version = '>= 2.6.0'
29
+ spec.summary = 'Write a short summary; RubyGems requires one.'
32
30
  spec.version = JekyllPluginTemplateVersion::VERSION
33
31
 
34
- spec.add_dependency "jekyll", ">= 3.5.0"
35
- spec.add_dependency "jekyll_plugin_logger"
36
- spec.add_dependency "key-value-parser"
37
- spec.add_dependency "git"
38
- spec.add_dependency "nokogiri"
39
- spec.add_dependency "os"
40
- spec.add_dependency "shellwords"
41
- spec.add_dependency "talk_like_a_pirate", ">= 0.2.2"
42
- spec.add_dependency "tty-prompt"
43
-
44
- # spec.add_development_dependency "debase"
45
- # spec.add_development_dependency "ruby-debug-ide"
32
+ spec.add_dependency 'jekyll', '>= 3.5.0'
33
+ spec.add_dependency 'jekyll_plugin_support', '>= 0.7.0'
34
+ spec.add_dependency 'git'
35
+ spec.add_dependency 'nokogiri'
36
+ spec.add_dependency 'os'
37
+ spec.add_dependency 'talk_like_a_pirate', '~> 0.2.2'
38
+ spec.add_dependency 'tty-prompt'
46
39
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Testing...
4
2
  module CategoryCombiner
5
3
  # For each catagory, makes a combined page from the collection pages, saves into _site/combined/#{collection.label}.html.
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Inspired by the badly broken example on https://jekyllrb.com/docs/plugins/generators/, and completely redone so it works.
4
2
  module CategoryIndexGenerator
5
3
  # Creates an index page for each catagory, plus a main index, all within a directory called _site/categories.
@@ -12,24 +10,24 @@ module CategoryIndexGenerator
12
10
  # This plugin is disabled unless _config.yml contains an entry for category_generator_enable and the value is not false
13
11
  return if site.config['category_generator_enable']
14
12
 
15
- return if site.config['env']['JEKYLL_ENV'] == "production"
13
+ return if site.config['env']['JEKYLL_ENV'] == 'production'
16
14
 
17
- index = Jekyll::PageWithoutAFile.new(site, site.source, 'categories', "index.html")
18
- index.data['layout'] = "default"
19
- index.data['title'] = "Post Categories"
20
- index.content = "<p>"
15
+ index = Jekyll::PageWithoutAFile.new(site, site.source, 'categories', 'index.html')
16
+ index.data['layout'] = 'default'
17
+ index.data['title'] = 'Post Categories'
18
+ index.content = '<p>'
21
19
 
22
20
  site.categories.each do |category, posts|
23
21
  new_page = Jekyll::PageWithoutAFile.new(site, site.source, 'categories', "#{category}.html")
24
- new_page.data['layout'] = "default"
22
+ new_page.data['layout'] = 'default'
25
23
  new_page.data['title'] = "Category #{category} Posts"
26
- new_page.content = "<p>" + posts.map do |post|
24
+ new_page.content = '<p>' + posts.map do |post|
27
25
  "<a href='#{post.url}'>#{post.data['title']}</a><br>"
28
26
  end.join("\n") + "</p>\n"
29
27
  site.pages << new_page
30
28
  index.content += "<a href='#{category}.html'>#{category}</a><br>\n"
31
29
  end
32
- index.content += "</p>"
30
+ index.content += '</p>'
33
31
  site.pages << index
34
32
  end
35
33
  # rubocop:enable Style/StringConcatenation, Metrics/AbcSize
data/lib/dumpers.rb CHANGED
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Methods to display Jekyll variable contents
4
2
  module Dumpers
5
3
  # See https://github.com/jekyll/jekyll/blob/master/lib/jekyll/collection.rb
@@ -8,7 +6,7 @@ module Dumpers
8
6
  # Metadata is a hash with at least these keys: output[Boolean], permalink[String]
9
7
  # selected methods: collection_dir, directory, entries, exists?, files, filtered_entries, relative_directory
10
8
  def collection_as_string(collection, indent_spaces)
11
- indent = " " * indent_spaces
9
+ indent = ' ' * indent_spaces
12
10
  result = <<~END_COLLECTION
13
11
  '#{collection.label}' collection within '#{collection.relative_directory}' subdirectory
14
12
  #{indent}Directory: #{collection.directory}
@@ -1,18 +1,14 @@
1
- # frozen_string_literal: true
2
-
3
- require "jekyll_plugin_logger"
4
- require "key_value_parser"
5
- require "shellwords"
1
+ require 'jekyll_plugin_support'
6
2
 
7
3
  module JekyllPluginBlockTagTemplate
8
- PLUGIN_NAME = "block_tag_template"
4
+ PLUGIN_NAME = 'block_tag_template'.freeze
9
5
  end
10
6
 
11
7
  # This is the module-level description.
12
8
  #
13
9
  # @example Heading for this example
14
10
  # Describe what this example does
15
- # {% block_tag_template "parameter" %}
11
+ # {% block_tag_template 'parameter' %}
16
12
  # Hello, world!
17
13
  # {% endblock_tag_template %}
18
14
  #
@@ -24,35 +20,27 @@ end
24
20
 
25
21
  module JekyllBlockTagPlugin
26
22
  # This class implements the Jekyll block tag functionality
27
- class MyBlock < Liquid::Block
28
- # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
29
- # @param tag_name [String] the name of the tag, which we already know.
30
- # @param argument_string [String] the arguments from the tag, as a single string.
31
- # @param _parse_context [Liquid::ParseContext] hash that stores Liquid options.
32
- # By default it has two keys: :locale and :line_numbers, the first is a Liquid::I18n object, and the second,
33
- # a boolean parameter that determines if error messages should display the line number the error occurred.
34
- # This argument is used mostly to display localized error messages on Liquid built-in Tags and Filters.
35
- # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
36
- # @return [void]
37
- def initialize(tag_name, argument_string, parse_context) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
38
- super
39
- @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
23
+ class MyBlock < JekyllSupport::JekyllBlock
24
+ include JekyllPluginTemplateVersion
25
+
26
+ REJECTED_ATTRIBUTES = %w[content excerpt next previous].freeze
40
27
 
41
- @argument_string = argument_string
28
+ # Method prescribed by the Jekyll support plugin.
29
+ # @return [String]
30
+ def render_impl(content)
31
+ @helper.gem_file __FILE__ # This enables attribution
42
32
 
43
- argv = Shellwords.split(argument_string) # Scans name/value arguments
44
- params = KeyValueParser.new.parse(argv) # Extracts key/value pairs, default value for non-existant keys is nil
45
- @param1 = params[:param1] # Obtain the value of parameter param1
46
- @param2 = params[:param2]
47
- @param3 = params[:param3]
48
- @param4 = params[:param4]
49
- @param5 = params[:param5]
50
- @param_x = params[:not_present] # The value of parameters that are present is nil, but displays as the empty string
33
+ @param1 = @helper.keys_values['param1'] # Obtain the value of parameter param1
34
+ @param2 = @helper.keys_values['param2']
35
+ @param3 = @helper.keys_values['param3']
36
+ @param4 = @helper.keys_values['param4']
37
+ @param5 = @helper.keys_values['param5']
38
+ @param_x = @helper.keys_values['not_present'] # The value of parameters that are present is nil, but displays as the empty string
51
39
 
52
40
  @logger.debug do
53
41
  <<~HEREDOC
54
- tag_name = '#{tag_name}'
55
- argument_string = '#{argument_string}'
42
+ tag_name = '#{@helper.tag_name}'
43
+ argument_string = '#{@helper.argument_string}'
56
44
  @param1 = '#{@param1}'
57
45
  @param2 = '#{@param2}'
58
46
  @param3 = '#{@param3}'
@@ -60,36 +48,14 @@ module JekyllBlockTagPlugin
60
48
  @param5 = '#{@param5}'
61
49
  @param_x = '#{@param_x}'
62
50
  params =
63
- #{params.map { |k, v| "#{k} = #{v}" }.join("\n ")}
51
+ #{@helper.keys_values.map { |k, v| "#{k} = #{v}" }.join("\n ")}
64
52
  HEREDOC
65
53
  end
66
- end
67
-
68
- REJECTED_ATTRIBUTES = %w[content excerpt next previous].freeze
69
54
 
70
- # Method prescribed by the Jekyll plugin lifecycle.
71
- # @param liquid_context [Liquid::Context]
72
- # @return [String]
73
- def render(liquid_context) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
74
- content = super # This underdocumented assignment returns the text within the block.
75
-
76
- @site = liquid_context.registers[:site]
77
- @config = @site.config
78
- @mode = @config.dig("env", "JEKYLL_ENV") || "development"
79
-
80
- # variables defined in pages are stored as hash values in liquid_context
81
- _assigned_page_variable = liquid_context['assigned_page_variable']
82
-
83
- # The names of front matter variables are hash keys for @page
84
- @page = liquid_context.registers[:page] # @page is a Jekyll::Drops::DocumentDrop
85
- # layout = @page['layout']
86
-
87
- @envs = liquid_context.environments.first
88
55
  @layout_hash = @envs['layout']
89
56
 
90
57
  @logger.debug do
91
58
  <<~HEREDOC
92
- liquid_context.scopes=#{liquid_context.scopes}
93
59
  mode="#{@mode}"
94
60
  page attributes:
95
61
  #{@page.sort
@@ -101,13 +67,16 @@ module JekyllBlockTagPlugin
101
67
 
102
68
  # Compute the return value of this Jekyll tag
103
69
  <<~HEREDOC
104
- <p style="color: green; background-color: yellow; padding: 1em; border: solid thin grey;">
70
+ <p style='color: green; background-color: yellow; padding: 1em; border: solid thin grey;'>
105
71
  #{content} #{@param1}
72
+ #{@helper.attribute if @helper.attribution}
106
73
  </p>
107
74
  HEREDOC
75
+ rescue StandardError => e
76
+ @logger.error { "#{self.class} died with a #{e.full_message}" }
77
+ exit 3
108
78
  end
79
+
80
+ JekyllPluginHelper.register(self, JekyllPluginBlockTagTemplate::PLUGIN_NAME)
109
81
  end
110
82
  end
111
-
112
- PluginMetaLogger.instance.info { "Loaded #{JekyllPluginBlockTagTemplate::PLUGIN_NAME} v#{JekyllPluginTemplateVersion::VERSION} plugin." }
113
- Liquid::Template.register_tag(JekyllPluginBlockTagTemplate::PLUGIN_NAME, JekyllBlockTagPlugin::MyBlock)
@@ -1,6 +1,4 @@
1
- # frozen_string_literal: true
2
-
3
- require "jekyll_plugin_logger"
1
+ require 'jekyll_plugin_logger'
4
2
 
5
3
  # @author Copyright 2020 {https://www.mslinn.com Michael Slinn}
6
4
  # Template for Jekyll filters.
@@ -14,12 +12,12 @@ module JekyllFilterTemplate
14
12
  # @param input_string [String].
15
13
  # @return [String] empty string if input_string has no contents except whitespace.
16
14
  # @example Use.
17
- # {{ "joy" | my_filter_template }} => <a href='https://www.google.com/search?q=joy' target='_blank' rel='nofollow'>joy</a>
15
+ # {{ 'joy' | my_filter_template }} => <a href='https://www.google.com/search?q=joy' target='_blank' rel='nofollow'>joy</a>
18
16
  def my_filter_template(input_string)
19
17
  # @context[Liquid::Context] is available here to look up variables defined in front matter, templates, page, etc.
20
18
 
21
19
  JekyllFilterTemplate.logger.debug do
22
- "Defined filters are: " + self.class # rubocop:disable Style/StringConcatenation
20
+ 'Defined filters are: ' + self.class # rubocop:disable Style/StringConcatenation
23
21
  .class_variable_get('@@global_strainer')
24
22
  .filter_methods.instance_variable_get('@hash')
25
23
  .map { |k, _v| k }
@@ -29,7 +27,7 @@ module JekyllFilterTemplate
29
27
  input_string.strip!
30
28
  JekyllFilterTemplate.logger.debug "input_string=#{input_string}"
31
29
  if input_string.empty?
32
- ""
30
+ ''
33
31
  else
34
32
  "<a href='https://www.google.com/search?q=#{input_string}' target='_blank' rel='nofollow'>#{input_string}</a>"
35
33
  end
@@ -1,10 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_support"
4
- require "active_support/inflector"
1
+ require 'active_support'
2
+ require 'active_support/inflector'
5
3
  require 'confidential_info_redactor'
6
- require "nokogiri"
7
- require "talk_like_a_pirate"
4
+ require 'nokogiri'
5
+ require 'talk_like_a_pirate'
8
6
 
9
7
  # Sample Jekyll Hook plugins
10
8
  module JekyllHookExamples
@@ -19,7 +17,7 @@ module JekyllHookExamples
19
17
  next unless webpage.data['pirate_talk']
20
18
 
21
19
  html = Nokogiri.HTML(webpage.output)
22
- html.css("p").each do |node|
20
+ html.css('p').each do |node|
23
21
  node.content = TalkLikeAPirate.translate(node.content)
24
22
  end
25
23
  webpage.output = html
@@ -43,9 +41,9 @@ module JekyllHookExamples
43
41
  def redact_all(content)
44
42
  tokens = ConfidentialInfoRedactor::Extractor.new.extract(content)
45
43
  ConfidentialInfoRedactor::Redactor.new(
46
- number_text: wrap(" number"), # This redactor is over-eager
47
- date_text: wrap(" date"),
48
- token_text: wrap(""),
44
+ number_text: wrap(' number'), # This redactor is over-eager
45
+ date_text: wrap(' date'),
46
+ token_text: wrap(''),
49
47
  tokens: tokens
50
48
  ).redact(content)
51
49
  end
@@ -55,11 +53,11 @@ module JekyllHookExamples
55
53
  # Uncomment the following lines, rebuild the plugin and view http://localhost:4444/
56
54
  # to see these hooks in action:
57
55
  #
58
- # Convert "Jekyll" to "Awesome Jekyll"
56
+ # Convert 'Jekyll' to 'Awesome Jekyll'
59
57
  # Jekyll::Hooks.register(:documents, :post_render, &modify_output)
60
58
  # Jekyll::Hooks.register(:pages, :post_render, &modify_output)
61
59
 
62
- # Convert "English" to "Pirate Talk"
60
+ # Convert 'English' to 'Pirate Talk'
63
61
  Jekyll::Hooks.register(:documents, :post_render, &pirate_translator)
64
62
  Jekyll::Hooks.register(:pages, :post_render, &pirate_translator)
65
63