jekyll-koziolekweb-tags 0.3.0 → 0.4.1

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: 43266d61852a499977df46bd3d4626c0368b121dc1d962857c41b0308470bf20
4
- data.tar.gz: f5f7fcdcade5cdead24b51f2cf2cd46a06cf3d71f42c0d9cdfb37ff441ba9749
3
+ metadata.gz: 70ab6aa5e1facb748323e5fd524b6ba17ce3269488b588f8910c152a18c44f65
4
+ data.tar.gz: 931601af22d327e6343beeae416904f848c075819345b9b6c1bf27686f853be6
5
5
  SHA512:
6
- metadata.gz: 5f8d6d2baee780bcfdc57cb95a4daea148c5a3650a309f0842fdee46b9bbf8179732685ea9fe3e8a97576ef22593851f1a2044a187e20754229f20ca0230536f
7
- data.tar.gz: 31c0a52191c88d868658edecfb63432844f9953609bcacdc6df4c25419d3a71dd85a80cfabb070125ba49228b6b2d6a119780e452aae0e77054b7aa877e2c543
6
+ metadata.gz: be6015623679f1d32cf740055b83bb69155ae58c00c8e66cf4df339f24450f45304b7c7cae46c7f4cb1d741e456ac8ec29e09431679308f0e279db44610d6225
7
+ data.tar.gz: 6e0e6128e2bf5dd18b80cb2994102a62978a50b74f6cc290a0ac999f84740361087780aa5b8d92b2f296cde3cfe4d3b9f32929a20a7f5685ae30e434a68d5873
data/.tool-versions ADDED
@@ -0,0 +1,2 @@
1
+ #ruby 2.6.5
2
+ ruby 3.4.3
data/Gemfile CHANGED
@@ -6,5 +6,7 @@ source "https://rubygems.org"
6
6
  gemspec
7
7
 
8
8
  gem "rake", "~> 13.0"
9
-
9
+ gem "minitest"
10
+ gem "liquid", "~> 4.0"
11
+ gem "shellwords"
10
12
  gem "jekyll", ENV["JEKYLL_VERSION"] if ENV["JEKYLL_VERSION"]
data/Rakefile CHANGED
@@ -1,4 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- task default: %i[]
4
+ require "rake/testtask"
5
+
6
+ # Definiowanie zadania testowego
7
+ Rake::TestTask.new do |t|
8
+ t.libs << "test"
9
+ t.test_files = FileList["test/test_*.rb"]
10
+ t.warning = true
11
+ end
12
+
13
+ # Domyślne zadanie: uruchom testy
14
+ task default: :test
15
+
@@ -3,7 +3,7 @@
3
3
  module Jekyll
4
4
  module Koziolekweb
5
5
  module Tags
6
- VERSION = "0.3.0"
6
+ VERSION = "0.4.1"
7
7
  end
8
8
  end
9
9
  end
@@ -1,73 +1,222 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "liquid"
4
+ require "jekyll"
5
+ require "jekyll/converters/markdown"
6
+ require "shellwords"
7
+ require "yaml"
8
+ require "cgi"
3
9
  require_relative "tags/version"
4
10
 
5
11
  module Koziolekweb
6
12
  module Tags
7
13
  class Listing < Liquid::Block
8
- @@file_state = {}
9
-
10
14
  def initialize(tag_name, markup, tokens)
11
15
  super
12
-
13
- matched = /(\w+)\s+["'](.*?)["']/.match(markup)
14
-
16
+ matched = markup.strip.match(/\A(\w+)\s+["'](.+?)["']\z/)
15
17
  if matched
16
18
  @lang = matched[1]
17
19
  @title = matched[2]
18
20
  else
19
- raise SyntaxError.new("
21
+ raise Liquid::SyntaxError, <<~ERROR.strip
20
22
  Invalid parameters for listing. Usage:
21
- {% listing lang 'title' %}
22
- code goes here
23
- {% endlisting %}
24
- got
25
- #{markup}")
23
+ {% listing lang 'title' %}
24
+ code goes here
25
+ {% endlisting %}
26
+ Got:
27
+ #{markup}
28
+ ERROR
26
29
  end
27
30
  end
28
31
 
29
32
  def render(context)
30
- current_file = context.registers[:page]["path"]
31
- @@file_state[current_file] ||= 0
32
- @@file_state[current_file] += 1
33
- content = super
34
- content_with_code_fence = "```#{@lang} #{content}```"
35
- title_with_parese = "#{@title}"
33
+ page = context.registers[:page]
34
+ current_file = page["path"] if page.respond_to?(:[]) && page["path"]
35
+ current_file ||= page.path if page.respond_to?(:path)
36
+ current_file ||= "__global__"
37
+ context.registers[:listing_count] ||= {}
38
+ context.registers[:listing_count][current_file] ||= 0
39
+ listing_number = (context.registers[:listing_count][current_file] += 1)
40
+ content = super.chomp
36
41
 
37
- "<p class='listing'> Listing #{@@file_state[current_file]}. #{@title_with_parese}</p>#{content_with_code_fence}"
42
+ markdown_converter = context.registers[:site].find_converter_instance(Jekyll::Converters::Markdown)
43
+ title_html = markdown_converter.convert(@title).strip.sub(%r{\A<p>(.*)</p>\z}, '\1')
44
+ markdown_code = "```#{@lang}\n#{content}\n```"
45
+ code_html = markdown_converter.convert(markdown_code).strip
46
+
47
+ <<~HTML
48
+ <p class='listing'> Listing #{listing_number}. #{title_html}</p>
49
+ #{code_html}
50
+ HTML
38
51
  end
39
52
  end
40
53
 
41
54
  class Offtop < Liquid::Block
55
+ VALID_DIRECTIONS = %w[right left].freeze
42
56
 
43
57
  def initialize(tag_name, markup, tokens)
44
58
  super
45
- @direction = markup
59
+ @params = parse_params(markup)
60
+
61
+ @direction = @params.fetch('direction', 'right').strip
62
+
63
+ unless self.class::VALID_DIRECTIONS.include?(@direction)
64
+ raise ArgumentError, "Invalid direction '#{@direction}'. Allowed values are: #{VALID_DIRECTIONS.join(', ')}"
65
+ end
46
66
  end
47
67
 
48
68
  def render(context)
49
69
  content = super
50
70
  "<aside class=\"offtopic f-#{@direction}\">#{content}</aside>"
51
71
  end
72
+
73
+ private
74
+
75
+ def parse_params(text)
76
+ params = {}
77
+ text.scan(/(\w+)\s*:\s*("[^"]*"|\S+)/).each do |key, val|
78
+ val = val.delete_prefix('"').delete_suffix('"') if val.start_with?('"')
79
+ params[key] = val
80
+ end
81
+ params
82
+ end
52
83
  end
53
84
 
54
85
  class YtVideo < Liquid::Tag
55
86
  def initialize(tag_name, video_id, tokens)
56
87
  super
57
88
  @video_id = video_id.strip
89
+
90
+ if @video_id.empty? || !valid_video_id?(@video_id)
91
+ raise Liquid::SyntaxError, "Invalid video ID: #{@video_id.inspect}"
92
+ end
93
+
58
94
  end
59
95
 
60
96
  def render(_context)
61
97
  <<~HTML
62
- <div class="video">
63
- <iframe src="https://www.youtube-nocookie.com/embed/#{@video_id}" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
64
- </div>
65
- HTML
98
+ <div class="video">
99
+ <iframe title="Youtube Video" src="https://www.youtube-nocookie.com/embed/#{@video_id}" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
100
+ </div>
101
+ HTML
66
102
  end
103
+
104
+ private
105
+
106
+ def valid_video_id?(video_id)
107
+ video_id.match?(/\A[\w-]{11}\z/)
108
+ end
109
+
67
110
  end
111
+
112
+ class Book < Liquid::Tag
113
+ MIN_ARGS = 5
114
+
115
+ def initialize(tag_name, markup, tokens)
116
+ super
117
+
118
+ args = Shellwords.split(markup)
119
+ raise Liquid::SyntaxError, "Invalid usage" if args.size < self::MIN_ARGS
120
+
121
+ @title, @author, @year, @isbn, @cover_url = args[0..4].map { _1.delete('"') }
122
+
123
+ unless @year.match?(/\A\d{4}\z/)
124
+ raise Liquid::SyntaxError, "Invalid publication year: #{@year.inspect}"
125
+ end
126
+
127
+ lang_arg = args.find { |s| s.start_with?("lang:") }
128
+ @lang = lang_arg&.split(":", 2)&.last || "en"
129
+
130
+ unless @lang.match?(/\A[a-z]{2}\z/i)
131
+ raise Liquid::SyntaxError, "Invalid language code: #{@lang.inspect}"
132
+ end
133
+ # Inicjalizacja LanguageManager
134
+ lang_data_path = File.join(Dir.pwd, '_data', 'lang') # Katalog z plikami językowymi
135
+ config_path = File.join(Dir.pwd, '_config.yml') # Ścieżka do pliku `_config.yml`
136
+ @language_manager = Koziolekweb::LanguageSupport::LanguageManager.new(config_path, lang_data_path)
137
+ end
138
+
139
+ def render(_context)
140
+ title_html = CGI.escapeHTML(@title)
141
+ author_html = CGI.escapeHTML(@author)
142
+ year_html = CGI.escapeHTML(@year)
143
+ isbn_html = CGI.escapeHTML(@isbn.to_s)
144
+ label_title = @language_manager.translate('title', @lang, 'Tytuł')
145
+ label_author = @language_manager.translate('author', @lang, 'Autor')
146
+ label_year = @language_manager.translate('year', @lang, 'Rok')
147
+ label_isbn = @language_manager.translate('isbn', @lang, 'ISBN')
148
+ cover_alt = @language_manager.translate('cover_alt', @lang, 'Okładka książki %{title} autorstwa %{author}')
149
+ .gsub('%{title}', @title)
150
+ .gsub('%{author}', @author)
151
+
152
+ <<~HTML
153
+ <div class="book">
154
+ <img src="#{@cover_url}" alt="#{cover_alt}" title="#{@title}" class="cover" />
155
+ <div class="book_desc">
156
+ <ul>
157
+ <li><span>#{label_title}: </span>#{title_html}</li>
158
+ <li><span>#{label_author}: </span>#{author_html}</li>
159
+ <li><span>#{label_year}: </span>#{year_html}</li>
160
+ #{@isbn.nil? ? "" : "<li><span>#{label_isbn}: </span>#{isbn_html}</li>"}
161
+ </ul>
162
+ </div>
163
+ </div>
164
+ HTML
165
+ end
166
+ end
167
+ end
168
+
169
+ module LanguageSupport
170
+ class LanguageManager
171
+ attr_reader :default_language
172
+ def initialize(config_path, lang_data_path)
173
+ @dictionary_cache = {}
174
+ @config_path = config_path
175
+ @lang_data_path = lang_data_path
176
+ @default_language = load_default_language
177
+ end
178
+
179
+ # Pobiera tłumaczenie dla danego klucza
180
+ def translate(key, lang = nil, default_value = nil)
181
+ lang ||= default_language
182
+ load_dictionary(lang)[key] || default_value
183
+ end
184
+
185
+ private
186
+
187
+ # Wczytanie domyślnego języka z pliku `_config.yml`
188
+ def load_default_language
189
+ if File.exist?(@config_path)
190
+ config = YAML.load_file(@config_path)
191
+ config['lang'] || 'en'
192
+ else
193
+ 'en'
194
+ end
195
+ end
196
+
197
+ # Wczytuje słownik dla danego języka
198
+ def load_dictionary(lang)
199
+ @dictionary_cache[lang] ||=
200
+ begin
201
+ dictionary_path = File.join(@lang_data_path, "#{lang}.yml")
202
+ if File.exist?(dictionary_path)
203
+ YAML.safe_load(File.read(dictionary_path), aliases: true)
204
+ else
205
+ {}
206
+ end
207
+ end
208
+ end
209
+ end
210
+
68
211
  end
69
212
  end
70
213
 
71
- Liquid::Template.register_tag('listing', Koziolekweb::Tags::Listing)
72
- Liquid::Template.register_tag('offtop', Koziolekweb::Tags::Offtop)
73
- Liquid::Template.register_tag('yt_video', Koziolekweb::Tags::YtVideo)
214
+ %w[listing offtop yt_video book].each do |tag|
215
+ class_name = tag.split('_').map(&:capitalize).join
216
+ begin
217
+ klass = Koziolekweb::Tags.const_get(class_name)
218
+ Liquid::Template.register_tag(tag, klass)
219
+ rescue NameError
220
+ warn "[WARN] Tag '#{tag}' not registered: Koziolekweb::Tags::#{class_name} not defined"
221
+ end
222
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-koziolekweb-tags
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koziolek
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-05-15 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: jekyll
@@ -38,11 +37,11 @@ executables: []
38
37
  extensions: []
39
38
  extra_rdoc_files: []
40
39
  files:
40
+ - ".tool-versions"
41
41
  - CHANGELOG.md
42
42
  - Gemfile
43
43
  - README.md
44
44
  - Rakefile
45
- - jekyll-koziolekweb-tags.gemspec
46
45
  - lib/jekyll/koziolekweb/tags.rb
47
46
  - lib/jekyll/koziolekweb/tags/version.rb
48
47
  - sig/jekyll/koziolekweb/tags.rbs
@@ -52,7 +51,6 @@ licenses:
52
51
  metadata:
53
52
  source_code_uri: https://github.com/Koziolek/jekyll-koziolekweb-tags
54
53
  changelog_uri: https://github.com/Koziolek/jekyll-koziolekweb-tags/CHANGELOG.md
55
- post_install_message:
56
54
  rdoc_options: []
57
55
  require_paths:
58
56
  - lib
@@ -67,8 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
65
  - !ruby/object:Gem::Version
68
66
  version: '0'
69
67
  requirements: []
70
- rubygems_version: 3.4.10
71
- signing_key:
68
+ rubygems_version: 3.6.7
72
69
  specification_version: 4
73
70
  summary: Set of structural tags that helps to organise article.
74
71
  test_files: []
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/jekyll/koziolekweb/tags/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "jekyll-koziolekweb-tags"
7
- spec.version = Jekyll::Koziolekweb::Tags::VERSION
8
- spec.authors = ["Koziolek"]
9
- spec.email = ["bjkuczynski@gmail.com"]
10
-
11
- spec.summary = "Set of structural tags that helps to organise article."
12
- spec.description = "Here you will find a set of tags that allow you to create code listings with numbering, notes using the <aside> element and more."
13
- spec.homepage = "https://github.com/Koziolek/jekyll-koziolekweb-tags"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.4.0"
16
- spec.add_dependency "jekyll", ">= 3.7", "< 5.0"
17
-
18
- # Specify which files should be added to the gem when it is released.
19
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
- spec.files = Dir.chdir(__dir__) do
21
- `git ls-files -z`.split("\x0").reject do |f|
22
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
23
- end
24
- end
25
- spec.bindir = "exe"
26
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
-
28
- spec.metadata["source_code_uri"] = "https://github.com/Koziolek/jekyll-koziolekweb-tags"
29
- spec.metadata["changelog_uri"] = "https://github.com/Koziolek/jekyll-koziolekweb-tags/CHANGELOG.md"
30
-
31
-
32
- spec.require_paths = ["lib"]
33
-
34
- # Uncomment to register a new dependency of your gem
35
- # spec.add_dependency "example-gem", "~> 1.0"
36
-
37
- # For more information and examples about making a new gem, check out our
38
- # guide at: https://bundler.io/guides/creating_gem.html
39
- end