Logic related to loading various versions of the index.html template. The actual template lives in
| (ns metabase.server.routes.index (:require [clojure.java.io :as io] [clojure.string :as str] [hiccup.util] [metabase.core.initialization-status :as init-status] [metabase.models.setting :as setting] [metabase.public-settings :as public-settings] [metabase.util.embed :as embed] [metabase.util.i18n :as i18n :refer [trs]] [metabase.util.json :as json] [metabase.util.log :as log] [ring.util.response :as response] [stencil.core :as stencil]) (:import (java.io FileNotFoundException))) |
(set! *warn-on-reflection* true) | |
(defn- base-href []
(let [path (some-> (public-settings/site-url) io/as-url .getPath)]
(str path "/"))) | |
(defn- escape-script [s] ;; Escapes text to be included in an inline <script> tag, in particular the string '</script' ;; https://stackoverflow.com/questions/14780858/escape-in-script-tag-contents/23983448#23983448 (str/replace s #"(?i)</script" "</scr\\\\ipt")) | |
(defn- fallback-localization [locale-or-name]
(json/encode
{"headers"
{"language" (str locale-or-name)
"plural-forms" "nplurals=2; plural=(n != 1);"}
"translations"
{ {"Metabase" {"msgid" "Metabase"
"msgstr" ["Metabase"]}}}})) | |
(defn- localization-json-file-name [locale-string] (format "frontend_client/app/locales/%s.json" (str/replace locale-string \- \_))) | |
(defn- load-localization* [locale-string]
(or
(when locale-string
(when-not (= locale-string "en")
(try
(slurp (or (io/resource (localization-json-file-name locale-string))
(when-let [fallback-locale (i18n/fallback-locale locale-string)]
(io/resource (localization-json-file-name (str fallback-locale))))
;; don't try to i18n the Exception message below, we have no locale to translate it to!
(throw (FileNotFoundException. (format "Locale '%s' not found." locale-string)))))
(catch Throwable e
(log/warn (.getMessage e))))))
(fallback-localization locale-string))) | |
Load a JSON-encoded map of localized strings for the current user's Locale. | (let [load-fn (memoize load-localization*)]
(defn- load-localization
[locale-override]
(load-fn (or locale-override (i18n/user-locale-string))))) |
(defn- load-inline-js* [resource-name] (slurp (io/resource (format "frontend_client/inline_js/%s.js" resource-name)))) | |
(def ^:private ^{:arglists '([resource-name])} load-inline-js (memoize load-inline-js*)) | |
(defn- load-template [path variables]
(try
(stencil/render-file path variables)
(catch IllegalArgumentException e
(let [message (trs "Failed to load template ''{0}''. Did you remember to build the Metabase frontend?" path)]
(log/error e message)
(throw (Exception. message e)))))) | |
(defn- load-entrypoint-template [entrypoint-name embeddable? {:keys [uri params nonce]}]
(load-template
(str "frontend_client/" entrypoint-name ".html")
(let [{:keys [anon-tracking-enabled google-auth-client-id], :as public-settings} (setting/user-readable-values-map #{:public})
;; We disable `locale` parameter on static embeds/public links (metabase#50313)
should-load-locale-params? (not embeddable?)]
{:bootstrapJS (load-inline-js "index_bootstrap")
:bootstrapJSON (escape-script (json/encode public-settings))
:assetOnErrorJS (load-inline-js "asset_loading_error")
:userLocalizationJSON (escape-script (load-localization (when should-load-locale-params? (:locale params))))
:siteLocalizationJSON (escape-script (load-localization (public-settings/site-locale)))
:nonceJSON (escape-script (json/encode nonce))
:language (hiccup.util/escape-html (public-settings/site-locale))
:favicon (hiccup.util/escape-html (public-settings/application-favicon-url))
:applicationName (hiccup.util/escape-html (public-settings/application-name))
:uri (hiccup.util/escape-html uri)
:baseHref (hiccup.util/escape-html (base-href))
:embedCode (when embeddable? (embed/head uri))
:enableGoogleAuth (boolean google-auth-client-id)
:enableAnonTracking (boolean anon-tracking-enabled)}))) | |
(defn- load-init-template []
(load-template
"frontend_client/init.html"
{:initJS (load-inline-js "init")})) | |
Response that serves up an entrypoint into the Metabase application, e.g. | (defn- entrypoint
[entrypoint-name embeddable? request respond _raise]
(respond
(-> (response/response (if (init-status/complete?)
(load-entrypoint-template entrypoint-name embeddable? request)
(load-init-template)))
(response/content-type "text/html; charset=utf-8")))) |
main index.html entrypoint. /public index.html entrypoint. /embed index.html entrypoint. | (def index (partial entrypoint "index" (not :embeddable))) (def public (partial entrypoint "public" :embeddable)) (def embed (partial entrypoint "embed" :embeddable)) |