File: edit-link-tag.rb

package info (click to toggle)
ruby-jekyll-github-metadata 2.15.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 712 kB
  • sloc: ruby: 2,355; javascript: 107; sh: 41; makefile: 6
file content (125 lines) | stat: -rw-r--r-- 3,759 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# frozen_string_literal: true

module Jekyll
  module GitHubMetadata
    class EditLinkTag < Liquid::Tag
      attr_reader :context

      # Defines an instance method that delegates to a hash's key
      #
      # hash_method -  a symbol representing the instance method to delegate to. The
      #                instance method should return a hash or respond to #[]
      # key         - the key to call within the hash
      # method      - (optional) the instance method the key should be aliased to.
      #               If not specified, defaults to the hash key
      # default     - (optional) value to return if value is nil (defaults to nil)
      #
      # Returns a symbol representing the instance method
      def self.def_hash_delegator(hash_method, key, method, default = nil)
        define_method(method) do
          hash = send(hash_method)
          if hash.respond_to? :[]
            hash[key.to_s] || default
          else
            default
          end
        end
      end

      MISSING_DATA_MSG = "Cannot generate edit URLs due to missing site.github data"
      LINK_TEXT_REGEX = %r!(?:\"(.*)\"|'(.*)')!.freeze

      extend Forwardable
      private def_hash_delegator :site,        :github,         :site_github, {}
      private def_hash_delegator :site_github, :repository_url, :repository_url
      private def_hash_delegator :site_github, :source,         :source, {}
      private def_hash_delegator :source,      :branch,         :branch
      private def_hash_delegator :source,      :path,           :source_path
      private def_hash_delegator :page,        :path,           :page_path

      def render(context)
        @context = context
        if link_text
          link
        else
          uri.to_s
        end
      end

      private

      def link_text
        @link_text ||= begin
          matches = @markup.match LINK_TEXT_REGEX
          matches[1] || matches[2] if matches
        end
      end

      def link
        "<a href=\"#{uri}\">#{link_text}</a>"
      end

      def uri
        if parts.any?(&:nil?)
          Jekyll.logger.warn "JekyllEditLink: ", MISSING_DATA_MSG
          ""
        else
          Addressable::URI.join(*parts_normalized).normalize
        end
      end

      def parts
        memoize_conditionally { [repository_url, "edit/", branch, source_path, page_path] }
      end

      def parts_normalized
        memoize_conditionally do
          parts.map.with_index do |part, index|
            part = remove_leading_slash(part.to_s)
            part = ensure_trailing_slash(part) unless index == parts.length - 1
            ensure_not_just_a_slash(part)
          end
        end
      end

      def page
        memoize_conditionally { context.registers[:page] }
      end

      # Utility function for compatibility with Jekyll 4.0
      def memoize_conditionally
        if renderer_cached?
          yield
        else
          dispatcher = "@#{caller_locations(1..1).first.label}".to_sym
          if instance_variable_defined?(dispatcher)
            instance_variable_get(dispatcher)
          else
            instance_variable_set(dispatcher, yield)
          end
        end
      end

      # Utility function to detect Jekyll 4.0
      def renderer_cached?
        @renderer_cached ||= context.registers[:site].liquid_renderer.respond_to?(:cache)
      end

      def site
        @site ||= context.registers[:site].site_payload["site"]
      end

      def remove_leading_slash(part)
        part.start_with?("/") ? part[1..-1] : part
      end

      def ensure_trailing_slash(part)
        part.end_with?("/") ? part : "#{part}/"
      end

      def ensure_not_just_a_slash(part)
        part == "/" ? "" : part
      end
    end
  end
end