phlex-ruby / phlex-rails

An object-oriented alternative to ActionView for Ruby on Rails.
https://www.phlex.fun
MIT License
232 stars 40 forks source link

Helper tags (CSRF, Vite) are missing from page source. #238

Closed konung closed 1 month ago

konung commented 1 month ago

Related to #152

I'm experiencing the same issue when running on Phlex 2.0 beta


# frozen_string_literal: true

class Views::Base < Phlex::HTML
  include Phlex::Rails::Helpers::Routes
  include Phlex::Rails::Helpers::LinkTo
  include Phlex::Rails::Helpers::ContentFor
  include Phlex::Rails::Helpers::CSRFMetaTags
  include Phlex::Rails::Helpers::CSPMetaTag
  include ActionView::Helpers
  include ViteRails::TagHelpers

  register_value_helper :vite_asset_path
  register_output_helper :vite_client_tag
  register_output_helper :vite_javascript_tag
  register_output_helper :vite_stylesheet_tag

  def around_template
    doctype
    html lang: "en" do
      head
      body do
        main do
          div class: "relative isolate mt-32 sm:mt-56 sm:pt-32" do
            div class: "mx-auto max-w-7xl px-6 lg:px-8" do
              div class: "mx-auto max-w-xl sm:text-center" do
                yield
              end
            end
          end
        end
      end
    end
  end

  private

  def head
    meta charset: "utf-8"
    meta name: "viewport", content: "width=device-width,initial-scale=1"
    meta name: "apple-mobile-web-app-capable", content: "yes"
    meta name: "mobile-web-app-capable", content: "yes"
    helpers.csrf_meta_tags
    # csp_meta_tag
    # content_for :head
    link rel: "icon", type: "image/png", href: "/icon.png"
    link rel: "icon", type: "image/svg+xml", href: "/icon.svg"
    link rel: "apple-touch-icon", href: "/icon.png"
    debugger if Rails.env.development?
    helpers.vite_client_tag
    helpers.vite_stylesheet_tag "application", data: { "turbo-track": "reload" }
    helpers.vite_javascript_tag "application", "data-turbo-track": "reload"
  end
end

So meta tags are showing up in my page source , but vite or csrf do not.

Notice that debugger statement - when I just check the return value of all of those helpers - they actually return values. THey are just missing from final output.

I tried, raw, unsafe_raw, with a helper prefix or not . They are just getting omitted from the buffer

    50|     # csp_meta_tag
    51|     # content_for :head
    52|     link rel: "icon", type: "image/png", href: "/icon.png"
    53|     link rel: "icon", type: "image/svg+xml", href: "/icon.svg"
    54|     link rel: "apple-touch-icon", href: "/icon.png"
=>  55|     debugger if Rails.env.development?
    56|     raw helpers.vite_client_tag
    57|     raw helpers.vite_stylesheet_tag "application", data: { "turbo-track": "reload" }
    58|     raw helpers.vite_javascript_tag "application", "data-turbo-track": "reload"
    59|   end
  # and 113 frames (use `bt' command for all frames)
(ruby)  raw helpers.vite_client_tag
"<script src=\"/vite-dev/@vite/client\" crossorigin=\"anonymous\" type=\"module\"></script>"
konung commented 1 month ago

I think I figured it out.

The problem was me trying to "cheat" the system and including everything from include ActionView::Helpers, who would have thunk it would cause issues (:sarcasm: )

Which also means my template was using raw from

require "active_support/core_ext/string/output_safety"

module ActionView # :nodoc:
  module Helpers # :nodoc:
    # = Action View Raw Output \Helpers
    module OutputSafetyHelper
      # This method outputs without escaping a string. Since escaping tags is
      # now default, this can be used when you don't want \Rails to automatically
      # escape tags. This is not recommended if the data is coming from the user's
      # input.
      #
      # For example:
      #
      #   raw @user.name
      #   # => 'Jimmy <alert>Tables</alert>'
      def raw(stringish)
        stringish.to_s.html_safe
      end

Instead of Phlex's implementation, leading to very unexpected results .

Come to think of it, I actually don't need to use raw anymore, since it's hangled by actual registered helpers now.

Here is a working version for reference:


# frozen_string_literal: true

class Views::Base < Phlex::HTML
  include Phlex::Rails::Helpers::Routes
  include Phlex::Rails::Helpers::LinkTo
  include Phlex::Rails::Helpers::ContentFor
  include Phlex::Rails::Helpers::CSRFMetaTags
  include Phlex::Rails::Helpers::CSPMetaTag
  include Phlex::Rails::Helpers::JavascriptIncludeTag
  include Phlex::Rails::Helpers::StylesheetLinkTag
  include Phlex::Rails::Helpers::PathToAsset
  # include ActionView::Helpers - removing the culprit, and adding individual helpers - 3 lines above.
  include ViteRails::TagHelpers

  register_value_helper :vite_asset_path
  register_output_helper :vite_client_tag
  register_output_helper :vite_javascript_tag
  register_output_helper :vite_stylesheet_tag

  def around_template
    doctype
    html lang: "en" do
      head
      body do

        main do
          div class: "relative isolate mt-32 sm:mt-56 sm:pt-32" do
            background_svg
            decorative_elements
            div class: "mx-auto max-w-7xl px-6 lg:px-8" do
              div class: "mx-auto max-w-xl sm:text-center" do
                super
              end
            end
          end
        end

      end
    end
  end

  private

  def head
    meta charset: "utf-8"
    title { page_title || "App" }
    meta name: "viewport", content: "width=device-width,initial-scale=1"
    meta name: "apple-mobile-web-app-capable", content: "yes"
    meta name: "mobile-web-app-capable", content: "yes"

    # Icons
    link rel: "icon", type: "image/png", href: "/icon.png"
    link rel: "icon", type: "image/svg+xml", href: "/icon.svg"
    link rel: "apple-touch-icon", href: "/icon.png"

    # CSRF
    csrf_meta_tags
    csp_meta_tag

    # Vite tags
    vite_client_tag
    vite_stylesheet_tag("application", data: { "turbo-track": "reload" })
    vite_javascript_tag("application", "data-turbo-track": "reload")
  end
end
stephannv commented 1 month ago

I think the problem was also that helpers.vite_client_tag was being used instead just vite_client_tag. Because using helpers.vite_client_tag you were using the rails helper and not the "phlex" method that outputs things to buffer.

konung commented 1 month ago

@stephannv - sorry, that' was me pasting the wrong example. I was trying to follow an older thread on the forum, where somebody suggested that , and trying to figure out where that's being called from.

Ultimately, the issue was me "over-including" action view modules 🤦‍♂️🤦‍♂️🤦‍♂️

joeldrapper commented 1 month ago

The problem is all these helpers are designed to return HTML safe strings. So in Phlex those strings just do nothing because they’re not pushed to the output buffer. The built in adapters and register_output_helper are essentially just doing raw helpers.foo_bar to push the values out as HTML.