3scale/porta

View on GitHub
app/helpers/webpack_helper.rb

Summary

Maintainability
A
1 hr
Test Coverage
# rubocop:disable Rails/HelperInstanceVariable
# frozen_string_literal: false

module WebpackHelper
  def load_webpack_manifest
    JSON.parse(File.read('public/packs/manifest.json'))
  rescue Errno::ENOENT
    raise "The webpack manifest file does not exist. Try running `rails assets:precompile`"
  end

  def webpack_manifest
    # Always get manifest.json on the fly in development mode
    return load_webpack_manifest if Rails.env.development?

    Rails.configuration.x.webpack.manifest ||= load_webpack_manifest
  end

  ##
  # Returns a string of HTML script and style tags, containing all chunks of one or more +packs+.
  # Chunks generated from ".ts" packs are located under the entrypoint with extension.
  # Chunks generated from ".scss" packs are located under the entrypoint without extension.
  #
  # +packs+ is a list of pack names, without extension (.ts, .js).
  #
  # FIXME: the entrypoints in manifest should not have extension .ts
  #
  # A RuntimeError is raised if one pack is not found in the manifest, possibly pointing out a typo.
  #
  # ⚠️ This method smells of :reek:NestedIterators and :reek:TooManyStatements
  #
  def javascript_packs_with_chunks_tag(*packs) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
    @packs ||= []
    tags = ''
    entrypoints = webpack_manifest['entrypoints']

    packs.each do |pack|
      entrypoint_with_extension = entrypoints["#{pack}.ts"] || {}
      entrypoint_without_extension = entrypoints[pack] || {}

      entrypoint = entrypoint_with_extension.deep_merge(entrypoint_without_extension) do |key, this_val, other_val|
        (this_val + other_val).uniq
      end
      raise "No entrypoint '#{pack}' in manifest" if entrypoint.empty?

      assets = entrypoint['assets']

      if (js = assets['js'])
        new_js_assets = js - @packs
        @packs.concat(new_js_assets)
        tags.concat(javascript_include_tag(*new_js_assets, defer: false), "\n")
      end

      if (css = assets['css']) # rubocop:disable Style/Next
        new_css_assets = css - @packs
        @packs.concat(new_css_assets)
        tags.concat(stylesheet_link_tag(*new_css_assets, defer: false))
      end
    end

    tags.html_safe # rubocop:disable Rails/OutputSafety
  end

  ##
  # Returns a string of HTML style tags, containing all CSS chunks of one or more +packs+.
  # Chunks generated from ".scss" packs are located under the entrypoint without extension.
  #
  # +packs+ is a list of pack names, without extension.
  #
  # A RuntimeError is raised if one pack is not found in the manifest, possibly pointing out a typo.
  #
  # ⚠️ This method smells of :reek:TooManyStatements
  #
  def stylesheet_packs_chunks_tag(*packs) # rubocop:disable, Metrics/MethodLength, Metrics/CyclomaticComplexity
    @packs ||= []
    tags = ''
    entrypoints = webpack_manifest['entrypoints']

    packs.each do |pack|
      entrypoint = entrypoints[pack] || {}
      raise "No entrypoint '#{pack}' in manifest" if entrypoint.empty?

      assets = entrypoint['assets']

      next unless (css = assets['css'])

      new_css_assets = css - @packs
      @packs.concat(new_css_assets)
      tags += stylesheet_link_tag(*new_css_assets, defer: false)
    end

    tags.html_safe # rubocop:disable Rails/OutputSafety
  end
end

# rubocop:enable Rails/HelperInstanceVariable