lib/svelte_on_rails/view_helpers.rb



module SvelteOnRails
  module ViewHelpers

    def svelte_component(filename, props = {})

      # check filename
      conf = SvelteOnRails::Configuration.instance
      cff = conf.components_folder_full
      file_path = cff + "#{filename}.svelte"
      if !File.exist?(file_path)
        raise file_not_found_messsage(filename)
      elsif conf.watch_changes? && !SvelteOnRails::Lib::Utils.file_exist_case_sensitive?(cff, filename + '.svelte')
        # on development environments we check case sensitivity too
        msg = "File found but Upper and lower case letters are incorrect\n" +
          "(This check is only on development environments when watch_changes is true):\n."
        raise file_case_sensitive_messsage(filename)
      end

      # check what to do

      rss = if props.key?(:ssr)
              props.delete(:ssr)
            else
              conf.ssr
            end
      unless [true, false, :auto].include?(rss)
        raise "Only true, false or auto are allowed for the argument #ssr"
      end
      ssr = (rss == :auto && request.headers['X-Turbo-Request-ID'].blank? || rss)

      hydrate = if props.key?(:hydrate)
                  props[:hydrate]
                else
                  true
                end

      # separate hashes

      props.delete(:hydrate)
      props.delete(:ssr)
      options = props.slice(:class, :id, :style)
      props.delete(:class)
      props.delete(:id)
      props.delete(:style)

      # set up html

      options[:class] = options[:class].to_s + ' svelte-component'
      options[:class] += ' please-hydrate-me-svelte-on-rails' if hydrate
      options[:data] ||= {}
      options[:data][:props] = props.to_json
      options[:data][:svelte_component] = filename

      if ssr

        # render server side

        start_time = Time.now
        comp = SvelteOnRails::Compiler.new(filename)
        comp.compile_if_changes
        rend = SvelteOnRails::Renderer.new(compiled_file: comp.compiled_file)
        res = rend.render(props)
        time = Time.now - start_time
        Rails.logger.info "  Rendered #{filename}.svelte server-side: #{time.round(3)}ms"

        content_tag(:div, options) do
          r = content_tag(:style, res['css'], type: 'text/css')
          r << res['html'].html_safe
        end

      else

        # render empty element
        Rails.logger.info "  Rendered #{filename}.svelte as empty element that will be mounted on the client side"
        content_tag(:div, options) {}

      end
    end

    def file_not_found_messsage(filename)
      conf = SvelteOnRails::Configuration.instance
      ff = conf.frontend_folder
      cf = conf.components_folder
      "svelte-on-rails gem, view helper #svelte_component\n\nFile not found:\n" +
        "#{conf.components_folder_full + "#{filename}.svelte"}\n\n" +
        "Your configurations are:\n\nfrontend_folder: «#{ff}»\ncomponents_folder: «#{cf}»\n.. and the filename attribute for the view helper: «#{filename}»\n"
    end

    def file_case_sensitive_messsage(filename)
      conf = SvelteOnRails::Configuration.instance
      ff = conf.frontend_folder
      cf = conf.components_folder
      "svelte-on-rails gem, view helper #svelte_component\n\n" +
        "File found but Upper and lower case letters are incorrect:\n" +
        "(This check is only on development environments when watch_changes is true)\n\n" +
        "#{conf.components_folder_full + "#{filename}.svelte"}\n\n" +
        "Your configurations are:\nfrontend_folder: «#{ff}»\ncomponents_folder: «#{cf}»\n.. and the filename attribute for the view helper: «#{filename}»\n"
    end

  end
end