jekyll-hive 1.1.1 → 2.0.0

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: 9961c6674e4ae1f94142229767b36b906805ff0a387a09b300e9fa20e9741438
4
- data.tar.gz: 17cea2edda4038ff804c389ff275610e0ce70db793ac234c0458345f11116d1c
3
+ metadata.gz: ffed7dc4de0f8360a6e98e9470af905ea77c3ef6832af01a45ec85ff29d4d0f5
4
+ data.tar.gz: 21db6c03f3351c65dfba021232b7a966e89eab71878b902756f721b9faf7112c
5
5
  SHA512:
6
- metadata.gz: 8e604ce1d31b67600ab0f1be7dc159328911dcefa4a6ea8fed5128e5e19d7a0a3d53087fc5727ec624e6fa62ed85bf3ea7f15f40a0d6f091897ac2ce1328f26a
7
- data.tar.gz: 10cce64b8f7cdedc47f35dd2f3a0dfb0f5f5bd720d5b6c4051d844406da498f720fb095a9d73fb96fe7cfc7e9b11d1c1741bf835e7f061559aaf562ffdd31448
6
+ metadata.gz: 869388677bfaa380eaed0d995122d1d88e335f459ffdf9bb3d78e76a19dd89efcc1259083bbbebea2b3375a72a7b919596ce264084ca240015b8b9e6b7d61e33
7
+ data.tar.gz: cbea377733876792ffbe40b2ecdce1a6d154868c6c0778fa9f4201e151878a5917ab8c1af05d1d5c6485b714385f308683ed1f18f45577368517a199c2612c07
data/README.md CHANGED
@@ -42,14 +42,46 @@ Use the tag as follows in your Jekyll pages, posts and collections:
42
42
  ```
43
43
  This will place the associated content on the page.
44
44
 
45
- ## Note About Turbolinks
45
+ ⚠️ The post body is published as-is, including any raw HTML the post contains. `jekyll-hive` does not sanitize it, so only embed posts you trust. The source link uses the post's `canonical_url` metadata when it is an `http`/`https` URL, otherwise the post's hive.blog URL.
46
46
 
47
- If you're using Turbolinks on your Jekyll site, you should consider adding the following line to your main includes, e.g. `_includes/head.html`:
47
+ As of version 2.0.0, `jekyll-hive` uses HAFBE-backed post retrieval and emits structured embed markup instead of injecting per-post scripts and styles.
48
+
49
+ ## Front-end dependencies
50
+
51
+ As of version 2.0.0, the `{% hive %}` tag emits structured embed markup and expects rendering dependencies to be loaded once by your site layout instead of being injected for every post.
52
+
53
+ At minimum, load your renderer and any supporting scripts/styles in a shared include such as `_includes/head.html` or your main layout. For example:
48
54
 
49
55
  ```html
50
56
  <script src='https://unpkg.com/steem-content-renderer'></script>
57
+ <script src='/assets/javascript/universal-bridge-against-phishing.js'></script>
58
+ <script src='/assets/javascript/lazysizes.min.js' async></script>
51
59
  ```
52
60
 
61
+ Then run a single page-level bootstrap pass against the generated embed targets, such as elements marked with `data-hive-render-target="true"`.
62
+
63
+ ## Legacy cache warning
64
+
65
+ If `jekyll-hive` detects cache entries created by the older inline-script / inline-style output format, it will warn once per build and recommend deleting `.jekyll-hive-cache` so the cache can be regenerated in the version 2.0.0 format.
66
+
67
+ ## Synthetic diff-match-patch conformance checks
68
+
69
+ The repo now includes a small synthetic diff-match-patch corpus under `spec/fixtures/diff_match_patch_vectors.json` to complement the real HAFBE history fixtures.
70
+
71
+ Purpose:
72
+ - pin down diff-match-patch semantics more surgically than the full history fixtures
73
+ - verify that percent-encoded inserted text remains literal when appropriate
74
+ - compare the Ruby `dimapa` path against optional external engines when available
75
+
76
+ Current helper layout:
77
+ - `script/dmp_engine_ruby.rb` — always-available Ruby helper used by the spec suite
78
+ - `script/dmp_engine_python.py` — optional Python helper using the `diff_match_patch` package
79
+ - `spec/fixtures/diff_match_patch_frozen_witnesses.json` — frozen external-engine witness outputs for durable regression coverage
80
+
81
+ If `.venv-dmp/` exists, the spec prefers that repo-local Python for the optional live Python agreement check. Otherwise it falls back to `python3` and cleanly skips the live Python comparison if the module is unavailable.
82
+
83
+ These synthetic vectors are not meant to replace the real HAFBE history fixtures; they exist to isolate patch semantics and cross-engine agreement.
84
+
53
85
  ## Jekyll Build
54
86
 
55
87
  When building your site with jekyll, you can continue to use the default command:
@@ -58,10 +90,10 @@ When building your site with jekyll, you can continue to use the default command
58
90
  jekyll build
59
91
  ```
60
92
 
61
- If you would like to provide an alternate node:
93
+ If you would like to provide an alternate HAFBE endpoint:
62
94
 
63
95
  ```bash
64
- NODE_URL=https://anyx.io jekyll build
96
+ HAFBE_API_URL=https://api.hive.blog/hafbe-api jekyll build
65
97
  ```
66
98
 
67
99
  ## Jekyll Clean
@@ -77,18 +109,17 @@ rm -rf .jekyll-hive-cache && jekyll clean && jekyll build
77
109
  #### I saw several messages like:
78
110
 
79
111
  ```
80
- Retrying: stoodkev/how-to-use-hivejs-or-other-modules-referencing-core-node-js-modules-on-react-native (Failed to open TCP connection to api.hive.blog:443 (getaddrinfo: nodename nor servname provided, or not known))
81
- Retrying: stoodkev/how-to-use-hivejs-or-other-modules-referencing-core-node-js-modules-on-react-native (Failed to open TCP connection to api.openhive.network:443 (getaddrinfo: nodename nor servname provided, or not known))
112
+ Retrying: author/permlink (HAFBE request failed for @author/permlink: HTTP 404)
82
113
  .
83
114
  .
84
115
  .
85
- Gave up on: stoodkev/how-to-use-hivejs-or-other-modules-referencing-core-node-js-modules-on-react-native
116
+ Gave up on: author/permlink
86
117
  ```
87
118
 
88
- Check your internet connection or provide an alternate node:
119
+ Check your internet connection, confirm the post exists, or provide an alternate HAFBE endpoint:
89
120
 
90
- ```
91
- NODE_URL=https://anyx.io jekyll build
121
+ ```bash
122
+ HAFBE_API_URL=https://api.hive.blog/hafbe-api jekyll build
92
123
  ```
93
124
 
94
125
  #### The post has changed on the blockchain, but `jekyll-hive` won't update to the latest post revision.
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dimapa'
4
+ require 'json'
5
+ require 'net/http'
6
+ require 'uri'
7
+
8
+ module Jekyll
9
+ module Hive
10
+ class HafbeClient
11
+ DEFAULT_API_URL = 'https://api.hive.blog/hafbe-api'.freeze
12
+
13
+ attr_reader :api_url
14
+
15
+ def initialize(api_url: ENV.fetch('HAFBE_API_URL', DEFAULT_API_URL))
16
+ @api_url = api_url
17
+ end
18
+
19
+ def fetch_post(author, permlink)
20
+ response = get("/accounts/#{escape(author)}/operations/comments/#{escape(permlink)}")
21
+ normalize_post(response)
22
+ rescue StandardError => e
23
+ raise "HAFBE request failed for @#{author}/#{permlink}: #{e.message}"
24
+ end
25
+
26
+ private
27
+
28
+ def get(path, params = {})
29
+ base = api_url.sub(%r{/$}, '')
30
+ uri = URI(base + path)
31
+ uri.query = URI.encode_www_form(params) unless params.empty?
32
+ response = Net::HTTP.get_response(uri)
33
+
34
+ unless response.is_a?(Net::HTTPSuccess)
35
+ raise "HTTP #{response.code}"
36
+ end
37
+
38
+ JSON.parse(response.body)
39
+ end
40
+
41
+ def normalize_post(payload)
42
+ operations = Array(payload['operations_result'])
43
+ comment_operations = operations.select do |entry|
44
+ entry.dig('op', 'type') == 'comment_operation'
45
+ end
46
+
47
+ raise 'Unexpected HAFBE response shape' if comment_operations.empty?
48
+
49
+ base_entry = comment_operations.find do |entry|
50
+ body = entry.dig('op', 'value', 'body').to_s
51
+ !diff_match_patch?(body)
52
+ end || comment_operations.first
53
+
54
+ post = deep_copy(base_entry.dig('op', 'value'))
55
+ raise 'Unexpected HAFBE response shape' unless post.is_a?(Hash)
56
+
57
+ post['created'] ||= base_entry['timestamp'] if base_entry['timestamp']
58
+
59
+ subsequent_entries = comment_operations.drop_while { |entry| entry != base_entry }.drop(1)
60
+ subsequent_entries.each do |entry|
61
+ apply_revision!(post, entry)
62
+ end
63
+
64
+ post
65
+ end
66
+
67
+ def apply_revision!(post, entry)
68
+ revision = entry.dig('op', 'value')
69
+ return unless revision.is_a?(Hash)
70
+
71
+ if revision.key?('title') && !revision['title'].to_s.empty?
72
+ post['title'] = revision['title']
73
+ end
74
+
75
+ if revision.key?('json_metadata') && !revision['json_metadata'].to_s.empty?
76
+ post['json_metadata'] = revision['json_metadata']
77
+ end
78
+
79
+ body = revision['body'].to_s
80
+ return if body.empty?
81
+
82
+ post['body'] = if diff_match_patch?(body)
83
+ apply_diff_match_patch(post['body'].to_s, body)
84
+ else
85
+ body
86
+ end
87
+ end
88
+
89
+ def diff_match_patch?(body)
90
+ body.start_with?('@@') || body.start_with?('@@ ')
91
+ end
92
+
93
+ def apply_diff_match_patch(original_body, patch_text)
94
+ dmp = DiMaPa.new
95
+ patches = dmp.patch_from_text(patch_text)
96
+ updated_body, = dmp.patch_apply(patches, original_body)
97
+ updated_body
98
+ end
99
+
100
+ def deep_copy(value)
101
+ Marshal.load(Marshal.dump(value))
102
+ end
103
+
104
+ def escape(segment)
105
+ URI.encode_www_form_component(segment.to_s)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -1,67 +1,73 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'cgi'
4
- require 'hive'
5
- require 'open-uri'
4
+ require 'json'
6
5
  require 'fileutils'
7
-
8
- Net::OpenTimeout = Class.new(RuntimeError) unless Net.const_defined?(:OpenTimeout)
9
- Net::ReadTimeout = Class.new(RuntimeError) unless Net.const_defined?(:ReadTimeout)
6
+ require 'set'
7
+ require 'time'
10
8
 
11
9
  module Jekyll
12
10
  module Hive
13
-
14
11
  # Use the tag as follows in your Jekyll pages, posts and collections:
15
- #
12
+ #
16
13
  # {% hive author/permlink %}
17
14
  class HiveTag < Liquid::Tag
15
+ LEGACY_CACHE_RECOMMENDATION = 'Delete .jekyll-hive-cache and rebuild so jekyll-hive can regenerate cache entries in the v2 format.'
16
+ V2_CACHE_MARKER = 'data-hive-render-target="true"'
17
+ LEGACY_CACHE_MARKERS = [
18
+ 'SteemContentRenderer.DefaultRenderer',
19
+ '<script src=\'https://unpkg.com/steem-content-renderer\'',
20
+ '<script src="https://unpkg.com/steem-content-renderer"',
21
+ '<script crossorigin=\'anonymous\' integrity=\'sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=\' src=\'https://code.jquery.com/jquery-3.5.1.slim.min.js\'',
22
+ '<script src=\'https://code.jquery.com/jquery-3.5.1.slim.min.js\'',
23
+ '<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"'
24
+ ].freeze
25
+
18
26
  def render(context)
19
- @encoding = context.registers[:site].config['encoding'] || 'utf-8'
20
- @settings = context.registers[:site].config['hive']
21
-
27
+ @site = context.registers[:site]
28
+ @encoding = @site.config['encoding'] || 'utf-8'
29
+ @settings = @site.config['hive'] || {}
30
+
22
31
  if (tag_contents = determine_arguments(@markup.strip))
23
32
  hive_slug = tag_contents[0]
24
33
  attempts = 0
25
34
  content = nil
26
- rebuild = ENV.fetch("JEKYLL_HIVE_REBUILD", 'false') == 'true'
27
-
35
+ rebuild = ENV.fetch('JEKYLL_HIVE_REBUILD', 'false') == 'true'
36
+
28
37
  loop do
29
38
  warn "Attempts for #{hive_slug}: #{attempts}" if attempts > 0
30
-
39
+
31
40
  if attempts > 4
32
41
  warn "Gave up on: #{hive_slug}"
33
42
  delete_content_cache(hive_slug)
34
43
  break
35
44
  end
36
-
45
+
37
46
  begin
38
- attempts = attempts + 1
39
-
40
- if !!rebuild && !!content_cache(hive_slug)
47
+ attempts += 1
48
+
49
+ if rebuild && content_cache(hive_slug)
41
50
  if content_age(hive_slug) > 9000
42
- # TODO quickly check if the cache should be cleared
43
-
44
51
  warn "Checking for changes: #{hive_slug}"
45
-
52
+
46
53
  if content_changed?(hive_slug)
47
54
  warn "Refreshing: #{hive_slug}"
48
55
  delete_content_cache(hive_slug)
49
56
  end
50
57
  end
51
-
58
+
52
59
  content_touch(hive_slug)
53
60
  end
54
-
61
+
55
62
  content = content_cache(hive_slug) || hive_tag(hive_slug)
56
-
63
+
57
64
  break
58
- rescue => e
65
+ rescue StandardError => e
59
66
  warn "Retrying: #{hive_slug} (#{e})"
60
- @api = nil
61
67
  sleep 3
62
68
  end
63
69
  end
64
-
70
+
65
71
  content_cache(hive_slug, content)
66
72
  else
67
73
  raise ArgumentError, <<~ERROR
@@ -73,80 +79,137 @@ module Jekyll
73
79
  ERROR
74
80
  end
75
81
  end
76
- private
82
+
83
+ private
84
+
77
85
  def cache_dir_path
78
86
  ENV.fetch('JEKYLL_HIVE_CACHE', '.jekyll-hive-cache')
79
87
  end
80
-
88
+
81
89
  def parse_key(hive_slug)
82
90
  hive_slug.gsub('/', '-')
83
91
  end
84
-
92
+
85
93
  def cached_file(hive_slug)
86
94
  key = parse_key(hive_slug)
87
-
95
+
88
96
  cache_dir_path + "/#{key}"
89
97
  end
90
-
98
+
91
99
  def content_cache(hive_slug, value = nil)
92
100
  key = parse_key(hive_slug)
93
-
94
- unless !!@content_cache
95
- @content_cache ||= {}
101
+
102
+ unless @content_cache
103
+ @content_cache = {}
104
+ @legacy_cache_warned_keys = Set.new
96
105
 
97
106
  FileUtils.mkdir_p(cache_dir_path)
98
-
107
+
99
108
  Dir.glob("#{cache_dir_path}/*") do |filename|
100
- next if File.directory? filename
101
-
102
- @content_cache[filename.split('/').last] = File.open(filename).read
109
+ next if File.directory?(filename)
110
+
111
+ cache_key = filename.split('/').last
112
+ cache_value = normalize_utf8(File.binread(filename))
113
+ @content_cache[cache_key] = cache_value
114
+ warn_if_legacy_cache_entry(cache_key, cache_value)
103
115
  end
104
116
  end
105
-
106
- if !!value && value != ''
107
- @content_cache[key] ||= value
108
-
117
+
118
+ if value && value != ''
119
+ normalized_value = normalize_utf8(value)
120
+ @content_cache[key] = normalized_value
121
+
109
122
  File.open(cached_file(hive_slug), 'wb') do |cache_file|
110
- cache_file.write(value)
123
+ cache_file.write(normalized_value)
111
124
  end
112
125
  end
113
-
126
+
114
127
  if @content_cache[key] == ''
115
128
  delete_content_cache(hive_slug)
116
-
129
+
117
130
  nil
118
131
  else
119
132
  @content_cache[key]
120
133
  end
121
134
  end
122
-
135
+
136
+ def warn_if_legacy_cache_entry(cache_key, cache_value)
137
+ return if @legacy_cache_warned_keys.include?(cache_key)
138
+ return unless legacy_cache_entry?(cache_value)
139
+ return if legacy_cache_warning_emitted?
140
+
141
+ @legacy_cache_warned_keys << cache_key
142
+ legacy_cache_warning_emitted!(cache_key)
143
+
144
+ warn <<~WARNING.gsub(/\s+/, ' ').strip
145
+ Detected legacy jekyll-hive cache entry #{cache_key.inspect} in #{cache_dir_path}.
146
+ #{LEGACY_CACHE_RECOMMENDATION}
147
+ WARNING
148
+ end
149
+
150
+ def legacy_cache_entry?(cache_value)
151
+ return false unless cache_value && cache_value != ''
152
+
153
+ normalized_cache_value = normalize_utf8(cache_value)
154
+ return false if normalized_cache_value.include?(V2_CACHE_MARKER)
155
+
156
+ LEGACY_CACHE_MARKERS.any? { |marker| normalized_cache_value.include?(marker) }
157
+ end
158
+
159
+ def legacy_cache_warning_emitted?
160
+ return false unless @site
161
+
162
+ @site.config['jekyll_hive_v2_legacy_cache_warning_emitted'] == true
163
+ end
164
+
165
+ def legacy_cache_warning_emitted!(cache_key)
166
+ return unless @site
167
+
168
+ @site.config['jekyll_hive_v2_legacy_cache_warning_emitted'] = true
169
+ @site.config['jekyll_hive_v2_legacy_cache_warning_key'] = cache_key
170
+ end
171
+
172
+ def normalize_utf8(value)
173
+ return '' if value.nil?
174
+
175
+ string = value.is_a?(String) ? value.dup : value.to_s
176
+ string.force_encoding(Encoding::UTF_8)
177
+
178
+ return string if string.valid_encoding?
179
+
180
+ string.encode(Encoding::UTF_8, Encoding::BINARY, invalid: :replace, undef: :replace, replace: '')
181
+ rescue EncodingError
182
+ value.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: '')
183
+ end
184
+
123
185
  def content_age(hive_slug)
124
186
  age = Time.now - File.mtime(cached_file(hive_slug)) rescue 0
125
187
  warn "Age for #{hive_slug}: #{age}"
126
-
188
+
127
189
  age
128
190
  end
129
-
191
+
130
192
  def content_touch(hive_slug)
131
193
  FileUtils.touch(cached_file(hive_slug))
132
194
  end
133
-
195
+
134
196
  def delete_content_cache(hive_slug)
197
+ @content_cache&.delete(parse_key(hive_slug))
135
198
  File.delete(cached_file(hive_slug)) rescue false
136
199
  end
137
-
200
+
138
201
  def determine_arguments(input)
139
202
  return unless input =~ /@?[^\/]+\/[^\/]+/i
140
-
203
+
141
204
  [input]
142
205
  end
143
-
144
- def api
145
- url = ENV.fetch('NODE_URL', 'https://api.hive.blog,https://api.openhive.network').split(',').sample
146
-
147
- @api ||= ::Hive::CondenserApi.new(url: url)
206
+
207
+ def hafbe_client
208
+ api_url = @settings['hafbe_api_url'] || ENV['HAFBE_API_URL'] || Jekyll::Hive::HafbeClient::DEFAULT_API_URL
209
+
210
+ @hafbe_client ||= Jekyll::Hive::HafbeClient.new(api_url: api_url)
148
211
  end
149
-
212
+
150
213
  def parse_slug(hive_slug)
151
214
  hive_slug = hive_slug.split('@').last
152
215
  hive_slug = hive_slug.split('/')
@@ -154,120 +217,54 @@ module Jekyll
154
217
  permlink = hive_slug[1..-1].join('/')
155
218
  permlink = permlink.split('?').first
156
219
  permlink = permlink.split('#').first
157
-
220
+
158
221
  [author, permlink]
159
222
  end
160
-
223
+
161
224
  def content_changed?(hive_slug)
162
225
  author, permlink = parse_slug(hive_slug)
163
226
  cached_created = File.mtime(cached_file(hive_slug)) rescue Time.now
227
+ content = fetch_content(author, permlink)
228
+ created = Time.parse(content.fetch('created').to_s + 'Z')
164
229
 
165
- # TODO find a better way to get the `created` timestamp, this is really
166
- # no faster than just parsing the content.
167
- api.get_content(author, permlink) do |content|
168
- created = Time.parse(content.created + 'Z')
169
-
170
- cached_created > created
171
- end
230
+ cached_created > created
172
231
  end
173
-
232
+
233
+ def fetch_content(author, permlink)
234
+ hafbe_client.fetch_post(author, permlink)
235
+ end
236
+
174
237
  def hive_tag(hive_slug)
175
238
  author, permlink = parse_slug(hive_slug)
176
-
177
- api.get_content(author, permlink) do |content|
178
- body = content.body
179
- metadata = JSON[content.json_metadata] rescue nil || {}
180
- canonical_url = metadata.fetch('canonical_url', "https://hive.blog/@#{author}/#{permlink}")
181
-
182
- # This will normalize image hoster proxy URLs that the author copied
183
- # from another post.
184
-
185
- body = body.gsub(/https:\/\/steemitimages.com\/[0-9]+x0\/https:\/\//, 'https://')
186
- body = body.gsub(/https:\/\/images.hive.blog\/[0-9]+x0\/https:\/\//, 'https://')
187
- body = body.gsub(/https:\/\/images.esteem.app\/[0-9]+x0\/https:\/\//, 'https://')
188
-
189
- scrape = URI::open(canonical_url).read
190
-
191
- if scrape.include? 'rel="canonical"'
192
- canonical_url = scrape.split('rel="canonical"')[1].split('"')[1]
193
- end
239
+ content = fetch_content(author, permlink)
240
+ body = normalize_utf8(content.fetch('body'))
241
+ metadata = JSON.parse(normalize_utf8(content.fetch('json_metadata', '{}'))) rescue {}
242
+ category = normalize_utf8(content['category']).sub(%r{^/+}, '')
243
+ canonical_url = normalize_utf8(metadata['canonical_url'])
244
+ canonical_url = ["https://hive.blog", category, "@#{author}", permlink].reject(&:empty?).join('/') unless canonical_url =~ %r{\Ahttps?://}i
194
245
 
195
- "<div id=\"content-#{author}-#{permlink}\">" + body + <<~DONE
246
+ body = body.gsub(/https:\/\/steemitimages.com\/[0-9]+x0\/https:\/\//, 'https://')
247
+ body = body.gsub(/https:\/\/images.hive.blog\/[0-9]+x0\/https:\/\//, 'https://')
248
+ body = body.gsub(/https:\/\/images.esteem.app\/[0-9]+x0\/https:\/\//, 'https://')
249
+
250
+ rendered_canonical_url = CGI.escapeHTML(canonical_url)
251
+ rendered_title = CGI.escapeHTML(normalize_utf8(content.fetch('title', '')))
252
+ rendered_author = CGI.escapeHTML(normalize_utf8(author))
253
+ rendered_permlink = CGI.escapeHTML(normalize_utf8(permlink))
254
+ container_id = "content-#{author}-#{permlink}"
255
+ rendered_container_id = CGI.escapeHTML(normalize_utf8(container_id))
256
+
257
+ normalize_utf8(<<~HTML)
258
+ <div class="hive-post-embed" data-hive-author="#{rendered_author}" data-hive-permlink="#{rendered_permlink}">
259
+ <div id="#{rendered_container_id}" class="hive-post-embed__content" data-hive-render-target="true">#{body}</div>
260
+ <footer class="hive-post-embed__source">
261
+ <span class="hive-post-embed__source-label">Source:</span>
262
+ <a href="#{rendered_canonical_url}">#{rendered_title}</a>
263
+ by
264
+ <a href="https://hive.blog/@#{rendered_author}">@#{rendered_author}</a>
265
+ </footer>
196
266
  </div>
197
- <script crossorigin='anonymous' integrity='sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=' src='https://code.jquery.com/jquery-3.5.1.slim.min.js'></script>
198
- <script src='https://unpkg.com/steem-content-renderer'></script>
199
- <!-- <script src="https://cdn.jsdelivr.net/npm/hive-content-renderer/dist/hive-content-renderer.min.js"></script> -->
200
- <script>
201
- $(document).ready(function() {
202
- try {
203
- const renderer = new SteemContentRenderer.DefaultRenderer({
204
- // const renderer = new HiveContentRenderer({
205
- baseUrl: "https://hive.blog/",
206
- breaks: true,
207
- skipSanitization: false,
208
- allowInsecureScriptTags: false,
209
- addNofollowToLinks: true,
210
- doNotShowImages: false,
211
- ipfsPrefix: "",
212
- assetsWidth: 640,
213
- assetsHeight: 480,
214
- imageProxyFn: (url) => url,
215
- usertagUrlFn: (account) => "/@#{author}",
216
- hashtagUrlFn: (hashtag) => "/#{permlink}",
217
- isLinkSafeFn: (url) => true,
218
- });
219
-
220
- const inputElem = $('#content-#{author}-#{permlink}').html();
221
- const outputElem = $('#content-#{author}-#{permlink}');
222
- const output = renderer.render(inputElem);
223
-
224
- outputElem.html(output);
225
- } catch(e) {
226
- console.log(e);
227
- }
228
- });
229
- </script>
230
- <style>
231
- #content-#{author}-#{permlink} {
232
- padding: 0 3rem;
233
- color: #444444;
234
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
235
- font-size: 16px;
236
- line-height: 1.8;
237
- text-shadow: 0 1px 0 #ffffff;
238
- padding: 0.5rem;
239
- }
240
- #content-#{author}-#{permlink} code {
241
- background: white;
242
- }
243
- #content-#{author}-#{permlink} a {
244
- border-bottom: 1px solid #444444; color: #444444; text-decoration: none;
245
- }
246
- #content-#{author}-#{permlink} a:hover {
247
- border-bottom: 0;
248
- }
249
- #content-#{author}-#{permlink} h1 {
250
- font-size: 2.2em;
251
- }
252
- #content-#{author}-#{permlink} h2, h3, h4, h5 {
253
- margin-bottom: 0;
254
- }
255
- #content-#{author}-#{permlink} header small {
256
- color: #999;
257
- font-size: 50%;
258
- }
259
- #content-#{author}-#{permlink} img {
260
- max-width: 100%;
261
- }
262
- </style>
263
- \n<hr />
264
- <p>
265
- See: <a href="#{canonical_url}">#{content.title}</a>
266
- by
267
- <a href="https://hive.blog/@#{author}">@#{author}</a>
268
- </p>
269
- DONE
270
- end
267
+ HTML
271
268
  end
272
269
  end
273
270
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module Hive
5
- VERSION = '1.1.1'
5
+ VERSION = '2.0.0'
6
6
  end
7
7
  end
data/lib/jekyll-hive.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'jekyll-hive/version'
4
+ require 'jekyll-hive/hafbe_client'
4
5
  require 'jekyll-hive/hive_tag'
5
6
 
6
7
  module Jekyll
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-hive
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Martin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-04 00:00:00.000000000 Z
11
+ date: 2026-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: hive-ruby
14
+ name: dimapa
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '0.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '0.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: jekyll
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -34,7 +34,7 @@ dependencies:
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
36
  version: '5.0'
37
- type: :development
37
+ type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
@@ -98,34 +98,6 @@ dependencies:
98
98
  - - "<"
99
99
  - !ruby/object:Gem::Version
100
100
  version: '1.0'
101
- - !ruby/object:Gem::Dependency
102
- name: webmock
103
- requirement: !ruby/object:Gem::Requirement
104
- requirements:
105
- - - "~>"
106
- - !ruby/object:Gem::Version
107
- version: '3.0'
108
- type: :development
109
- prerelease: false
110
- version_requirements: !ruby/object:Gem::Requirement
111
- requirements:
112
- - - "~>"
113
- - !ruby/object:Gem::Version
114
- version: '3.0'
115
- - !ruby/object:Gem::Dependency
116
- name: vcr
117
- requirement: !ruby/object:Gem::Requirement
118
- requirements:
119
- - - "~>"
120
- - !ruby/object:Gem::Version
121
- version: '6.0'
122
- type: :development
123
- prerelease: false
124
- version_requirements: !ruby/object:Gem::Requirement
125
- requirements:
126
- - - "~>"
127
- - !ruby/object:Gem::Version
128
- version: '6.0'
129
101
  - !ruby/object:Gem::Dependency
130
102
  name: simplecov
131
103
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +136,7 @@ files:
164
136
  - LICENSE
165
137
  - README.md
166
138
  - lib/jekyll-hive.rb
139
+ - lib/jekyll-hive/hafbe_client.rb
167
140
  - lib/jekyll-hive/hive_tag.rb
168
141
  - lib/jekyll-hive/version.rb
169
142
  homepage: https://github.com/inertia186/jekyll-hive