<commit_before>defmodule Plug.PlugOffline do
  import Plug.Conn

  @spec init(map) :: map
  def init(options) do
    options
  end

  @spec call(map, map) :: map
  def call(conn, options) do
    if "/#{conn.path_info}" == options[:at] do
      conn
      |> put_resp_content_type("text/cache-manifest")
      |> send_resp(200, cache_content(options))
      |> halt
    else
      conn
    end
  end

  @spec cache_content(map) :: String.t
  def cache_content(options) do
    body = ["CACHE MANIFEST", cache_key(options[:cache], options[:base_path])]
    body = body ++ cache(options)
    body = body ++ network(options)
    body = body ++ fallback(options)

    body
    |> Enum.join("\n")
  end

  # When inline option present do not generate cache manifest entry for the assets file, though
  # the digest is still based on the content of all assets. Which make update possible when
  # assets changes
  defp cache(%{offline_asset: true, inline: true} = _opts) do
    []
  end

  defp cache(opts) do
    opts[:cache]
  end

  # https://bordeltabernacle.github.io/2016/01/04/notes-on-elixir-pattern-matching-maps.html
  defp network(%{network: _network} = opts) do
    ["NETWORK:" | opts[:network]]
  end

  defp network(_opts) do
    []
  end

  defp fallback(%{fallback: _fallback} = opts) do
    ["FALLBACK:" | opts[:fallback]]
  end

  defp fallback(_opts) do
    []
  end

  @spec cache_key(nil, String.t) :: String.t
  defp cache_key(nil, _path) do
    ''
  end

  @spec cache_key(list(String.t), String.t) :: String.t
  defp cache_key(keys, base_path) do
    keys
    |> Enum.sort
    |> Enum.map(&digest_file(&1, base_path))
    |> Enum.join
    |> magic_comment
  end

  @spec digest_file(String.t, nil) :: String.t
  defp digest_file(file_name, nil) do
    read_file(file_name)
  end

  @spec digest_file(String.t, String.t) :: String.t
  defp digest_file(file_name, base_path) do<commit_msg>make cache manifest methods chainable<commit_after>defmodule Plug.PlugOffline do
  import Plug.Conn

  @spec init(map) :: map
  def init(options) do
    options
  end

  @spec call(map, map) :: map
  def call(conn, options) do
    if "/#{conn.path_info}" == options[:at] do
      conn
      |> put_resp_content_type("text/cache-manifest")
      |> send_resp(200, cache_content(options))
      |> halt
    else
      conn
    end
  end

  @spec cache_content(map) :: String.t
  def cache_content(options) do
    ["CACHE MANIFEST", cache_key(options[:cache], options[:base_path])]
    |> cache(options)
    |> network(options)
    |> fallback(options)
    |> Enum.join("\n")
  end

  # When inline option present do not generate cache manifest entry for the assets file, though
  # the digest is still based on the content of all assets. Which make update possible when
  # assets changes
  defp cache(body, %{offline_asset: true, inline: true} = _opts) do
    body
  end

  defp cache(body, opts) do
    body ++ opts[:cache]
  end

  # https://bordeltabernacle.github.io/2016/01/04/notes-on-elixir-pattern-matching-maps.html
  defp network(body, %{network: _network} = opts) do
    body ++ ["NETWORK:" | opts[:network]]
  end

  defp network(body, _opts) do
    body
  end

  defp fallback(body, %{fallback: _fallback} = opts) do
    body ++ ["FALLBACK:" | opts[:fallback]]
  end

  defp fallback(body, _opts) do
    body
  end

  @spec cache_key(nil, String.t) :: String.t
  defp cache_key(nil, _path) do
    ''
  end

  @spec cache_key(list(String.t), String.t) :: String.t
  defp cache_key(keys, base_path) do
    keys
    |> Enum.sort
    |> Enum.map(&digest_file(&1, base_path))
    |> Enum.join
    |> magic_comment
  end

  @spec digest_file(String.t, nil) :: String.t
  defp digest_file(file_name, nil) do
    read_file(file_name)
  end

  @spec digest_file(String.t, String.t) :: String.t
  defp digest_file(file_name, base_path) do
{'fraction_non_alphanumeric': 0.12698412698412698, 'fraction_numerical': 0.00624512099921936, 'mean_word_length': 3.252212389380531, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 22, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1844545', 'n_tokens_mistral': 1397, 'n_tokens_neox': 1321, 'n_words': 347}