lib/jekyll-twitter-plugin.rb in jekyll-twitter-plugin-2.0.0 vs lib/jekyll-twitter-plugin.rb in jekyll-twitter-plugin-2.1.0
- old
+ new
@@ -1,6 +1,7 @@
# frozen_string_literal: true
+
require "fileutils"
require "net/http"
require "uri"
require "ostruct"
require "json"
@@ -9,16 +10,18 @@
##
# A Liquid tag plugin for Jekyll that renders Tweets from Twitter API.
# https://github.com/rob-murray/jekyll-twitter-plugin
#
module TwitterJekyll
+ VERSION = "2.0.0".freeze
+ REFER_TO_README = "Please see 'https://github.com/rob-murray/jekyll-twitter-plugin' for usage.".freeze
+ LIBRARY_VERSION = "jekyll-twitter-plugin-v#{VERSION}".freeze
+ REQUEST_HEADERS = { "User-Agent" => LIBRARY_VERSION }.freeze
+
# TODO: remove after deprecation cycle
CONTEXT_API_KEYS = %w(consumer_key consumer_secret access_token access_token_secret).freeze
ENV_API_KEYS = %w(TWITTER_CONSUMER_KEY TWITTER_CONSUMER_SECRET TWITTER_ACCESS_TOKEN TWITTER_ACCESS_TOKEN_SECRET).freeze
- REFER_TO_README = "Please see 'https://github.com/rob-murray/jekyll-twitter-plugin' for usage.".freeze
- LIBRARY_VERSION = "jekyll-twitter-plugin-v2.0.0".freeze
- REQUEST_HEADERS = { "User-Agent" => LIBRARY_VERSION }.freeze
# Cache class that writes to filesystem
# TODO: Do i really need to cache?
# @api private
class FileCache
@@ -26,27 +29,26 @@
@cache_folder = File.expand_path path
FileUtils.mkdir_p @cache_folder
end
def read(key)
- file_to_read = cache_file(cache_filename(key))
+ file_to_read = cache_file(key)
JSON.parse(File.read(file_to_read)) if File.exist?(file_to_read)
end
def write(key, data)
- file_to_write = cache_file(cache_filename(key))
- data_to_write = JSON.generate data.to_h
+ file_to_write = cache_file(key)
File.open(file_to_write, "w") do |f|
- f.write(data_to_write)
+ f.write(JSON.generate(data.to_h))
end
end
private
- def cache_file(filename)
- File.join(@cache_folder, filename)
+ def cache_file(key)
+ File.join(@cache_folder, cache_filename(key))
end
def cache_filename(cache_key)
"#{cache_key}.cache"
end
@@ -73,11 +75,10 @@
http.open_timeout = 5
http.get uri.request_uri, REQUEST_HEADERS
end
handle_response(api_request, response)
-
rescue Timeout::Error => e
ErrorResponse.new(api_request, e.class.name).to_h
end
private
@@ -140,15 +141,26 @@
# @api public
class TwitterTag < Liquid::Tag
ERROR_BODY_TEXT = "<p>Tweet could not be processed</p>".freeze
OEMBED_ARG = "oembed".freeze
+ URL_OR_STRING_PARAM = /^("|')?(http|https):\/\//i
+
attr_writer :cache # for testing
def initialize(_name, params, _tokens)
super
- @api_request = parse_params(params)
+
+ # Test if first arg is a URL or starts with oembed,
+ # otherwise its a Jekyll variable. TODO: remove oembed after deprecation cycle
+ if params =~ URL_OR_STRING_PARAM || params.to_s.start_with?(OEMBED_ARG)
+ @fetch_from_context = false
+ @api_request = parse_params_from_string(params)
+ else
+ @fetch_from_context = true
+ @variable_params = normalize_string_params(params)
+ end
end
# Class that implements caching strategy
# @api private
def self.cache_klass
@@ -156,17 +168,27 @@
end
# Return html string for Jekyll engine
# @api public
def render(context)
+ if fetch_from_context?
+ variable_name, *params = @variable_params
+ tweet_url = context[variable_name]
+ @api_request = parse_params_from_array [tweet_url, *params]
+ end
+
api_secrets_deprecation_warning(context) # TODO: remove after deprecation cycle
response = cached_response || live_response
html_output_for(response)
end
private
+ def fetch_from_context?
+ @fetch_from_context
+ end
+
def cache
@cache ||= self.class.cache_klass.new("./.tweet-cache")
end
def api_client
@@ -195,40 +217,54 @@
def cached_response
response = cache.read(@api_request.cache_key)
build_response(response) unless response.nil?
end
+ def parse_params_from_string(str)
+ args = normalize_string_params(str)
+ parse_params(args)
+ end
+
+ def parse_params_from_array(arr)
+ parse_params(arr)
+ end
+
# Return an `ApiRequest` with the url and arguments
# @api private
- def parse_params(params)
- args = params.split(/\s+/).map(&:strip)
- invalid_args!(args) unless args.any?
+ def parse_params(args)
+ invalid_args!(args) unless args.compact.any?
if args[0].to_s == OEMBED_ARG # TODO: remove after deprecation cycle
arguments_deprecation_warning(args)
args.shift
end
url, *api_args = args
- ApiRequest.new(url, parse_args(api_args))
+ ApiRequest.new(url, hash_from_args(api_args))
end
+ # Take input arguments, remove quotes & return array of argument values
+ # @api private
+ def normalize_string_params(str)
+ str.to_s.gsub(/"|'/, "").split(/\s+/).map(&:strip)
+ end
+
# Transform 'a=b x=y' tag arguments into { "a" => "b", "x" => "y" }
# @api private
- def parse_args(args)
- args.each_with_object({}) do |arg, params|
+ def hash_from_args(args)
+ args.each_with_object({}) do |arg, results|
k, v = arg.split("=").map(&:strip)
if k && v
v = Regexp.last_match[1] if v =~ /^'(.*)'$/
- params[k] = v
+ results[k] = v
end
end
end
# Format a response hash
# @api private
- def build_response(h)
- OpenStruct.new(h)
+ def build_response(response_hash)
+ OpenStruct.new(response_hash)
end
# TODO: remove after deprecation cycle
def arguments_deprecation_warning(args)
warn "#{LIBRARY_VERSION}: Passing '#{OEMBED_ARG}' as the first argument is not required anymore. This will result in an error in future versions.\nCalled with #{args.inspect}"