lib/ariadne/yard/docs_helper.rb



# frozen_string_literal: true

# :nocov:
module Ariadne
  # :nodoc:
  module Yard
    # Helper methods to use for yard documentation
    module DocsHelper
      def one_of(enumerable, lower: false, sort: false)
        # Sort the array if requested
        if sort && !enumerable.nil?
          enumerable = enumerable.sort do |a, b|
            a.instance_of?(b.class) ? a <=> b : a.class.to_s <=> b.class.to_s
          end
        end

        values =
          case enumerable
          when Hash
            enumerable.map do |key, value|
              "#{pretty_value(key)} (#{pretty_value(value)})"
            end
          else
            enumerable.map do |key|
              pretty_value(key)
            end
          end

        prefix = "One of"
        prefix = prefix.downcase if lower

        "#{prefix} #{values.to_sentence(two_words_connector: " or ", last_word_connector: ", or ")}."
      end

      def link_to_accessibility
        "[Accessibility](#accessibility)"
      end

      def link_to_html_attrs_docs
        "[HTML attributes](/html-attrs)"
      end

      def link_to_typography_docs
        "[Typography](/system-arguments#typography)"
      end

      def link_to_component(component)
        class_name, short_name = component_and_short_name(component)

        "[#{class_name}](/components/#{short_name.downcase})"
      end

      def link_to_heroicons
        "[Heroicon](https://heroicons.com/)"
      end

      def link_to_heading_practices
        "[Learn more about best heading practices (WAI Headings)](https://www.w3.org/WAI/tutorials/page-structure/headings/)"
      end

      def component_and_short_name(component)
        name = component.name.sub("::Preview", "::Component")
        m = name.match(/Ariadne::(?<name>.*)::Component/)
        if m.nil? # e.g. `Ariadne::Behaviors::Caption`; three paths instad of four
          m = name.match(/Ariadne::(?<name>.*)/)
        end
        [name, m[:name]]
      end

      def pretty_default_value(tag, component)
        default = tag.respond_to?(:defaults) ? tag.defaults : nil

        # For slots; eg.,
        # `renders_one :title, lambda { |type: :subheading, **options|`;
        # `type` has a default value of `:subheading`.
        if default.nil?
          results = /#{tag.name}:\s*([^,\s]+)/.match(tag.object.source)
          default = results[1] if results
        end

        return "" unless default

        constant_name = "#{component.name}::#{default}"
        constant_value = default.safe_constantize || constant_name.safe_constantize

        return pretty_value(default) if constant_value.nil?

        pretty_value(constant_value)
      end

      def pretty_value(val)
        case val
        when nil
          "`nil`"
        when Symbol
          "`:#{val}`"
        else
          "`#{val}`"
        end
      end
    end

    DocsHelper.extend(DocsHelper)
  end
end
# :nocov: