{-| Module: IHP.PageHead.ViewFunctions Description: Manage the @<title>@ and @<meta>@ tags of your HTML pages Copyright: (c) digitally induced GmbH, 2021 -} module IHP.PageHead.ViewFunctions ( pageTitle , pageTitleOrDefault , pageTitleOrNothing , descriptionOrDefault , ogTitleOrDefault , ogTypeOrDefault , ogDescriptionOrDefault , ogUrl , ogImage , module IHP.PageHead.ControllerFunctions -- | Re-export as we want to call setTitle from the beforeRender hook ) where import IHP.Prelude import IHP.PageHead.Types import IHP.Controller.Context import IHP.PageHead.ControllerFunctions import IHP.HSX.QQ (hsx) import Text.Blaze.Html5 (Html) -- | Returns the current page title. The title can be set using @setTitle "my title"@ from the action. -- -- If the title hasn't been set yet, this will return an empty string. You can also use 'pageTitleOrDefault' to pass a custom default title. -- -- You can use this inside your @<title>@ tag like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitle}</title> -- > </head> -- > |] -- -- -- *App-wide default title:* -- -- You can set a app-wide default title by calling 'setTitle' from the @FrontController.hs@: -- -- > instance InitControllerContext Web where -- > initContext = do -- > setLayout defaultLayout -- > initAutoRefresh -- > setTitle "Jobs" -- -- -- *View-specific title:* -- -- You can set a custom title inside the view by calling 'setTitle' inside the 'beforeRender' hook. -- -- > module JobSite.View.JobPositions.Show where -- > -- > instance View ShowView where -- > beforeRender ShowView { .. } = do -- > setTitle "Custom title" -- > -- > html ShowView { .. } = [hsx|..|] pageTitle :: (?context :: ControllerContext) => Text pageTitle :: (?context::ControllerContext) => Text pageTitle = (?context::ControllerContext) => Text -> Text Text -> Text pageTitleOrDefault Text "" -- | Returns the current page title, like 'pageTitle' but returns a provided default value instead of an empty string if no title is set. -- -- You can use this inside your @<title>@ tag like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitleOrDefault "My Application"}</title> -- > </head> -- > |] pageTitleOrDefault :: (?context :: ControllerContext) => Text -> Text pageTitleOrDefault :: (?context::ControllerContext) => Text -> Text pageTitleOrDefault Text defaultValue = Maybe Text (?context::ControllerContext) => Maybe Text pageTitleOrNothing Maybe Text -> (Maybe Text -> Text) -> Text forall {t1} {t2}. t1 -> (t1 -> t2) -> t2 |> Text -> Maybe Text -> Text forall a. a -> Maybe a -> a fromMaybe Text defaultValue -- | Returns the current page title or Nothing if not set yet pageTitleOrNothing :: (?context :: ControllerContext) => Maybe Text pageTitleOrNothing :: (?context::ControllerContext) => Maybe Text pageTitleOrNothing = case forall value. (?context::ControllerContext, Typeable value) => Maybe value maybeFromFrozenContext @PageTitle of Just (PageTitle Text title) -> Text -> Maybe Text forall a. a -> Maybe a Just Text title Maybe PageTitle Nothing -> Maybe Text forall a. Maybe a Nothing -- | Returns the meta og:title element. The og:title can be set using @setOGTitle "my title"@ from the view. -- -- You can use this inside your Layout like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitle}</title> -- > {ogTitleOrDefault "default title"} -- > </head> -- > |] -- -- -- *View-specific og:title:* -- -- You can override the default og:title inside the view by calling 'setOGTitle' inside the 'beforeRender' hook: -- -- > module JobSite.View.JobPositions.Show where -- > -- > instance View ShowView where -- > beforeRender ShowView { .. } = do -- > setOGTitle "Custom title" -- > -- > html ShowView { .. } = [hsx|..|] ogTitleOrDefault :: (?context :: ControllerContext) => Text -> Html ogTitleOrDefault :: (?context::ControllerContext) => Text -> Html ogTitleOrDefault Text defaultValue = [hsx|<meta property="og:title" content={content}/>|] where content :: Text content = case forall value. (?context::ControllerContext, Typeable value) => Maybe value maybeFromFrozenContext @OGTitle of Just (OGTitle Text title) -> Text title Maybe OGTitle Nothing -> Text defaultValue -- | Returns @<meta name="description" content="Lorem Ipsum">@ element. The description can be set using @setDescription "my description"@ from the view. -- -- You can use this inside your Layout like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitle}</title> -- > {descriptionOrDefault "CO2 Database"} -- > </head> -- > |] -- -- -- *View-specific description:* -- -- You can override the default description inside the view by calling 'setDescription' inside the 'beforeRender' hook: -- -- > module JobSite.View.JobPositions.Show where -- > -- > instance View ShowView where -- > beforeRender ShowView { .. } = do -- > setDescription "The CO2 Footprint of beef is about 67kg CO2 per 1kg of beef." -- > -- > html ShowView { .. } = [hsx|..|] descriptionOrDefault :: (?context :: ControllerContext) => Text -> Html descriptionOrDefault :: (?context::ControllerContext) => Text -> Html descriptionOrDefault Text defaultValue = [hsx|<meta name="description" content={content}/>|] where content :: Text content = case forall value. (?context::ControllerContext, Typeable value) => Maybe value maybeFromFrozenContext @PageDescription of Just (PageDescription Text description) -> Text description Maybe PageDescription Nothing -> Text defaultValue -- | Returns the meta og:type element. The og:type can be set using @setOGType "data"@ from the view. -- -- You can use this inside your Layout like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitle}</title> -- > {ogTypeOrDefault "data"} -- > </head> -- > |] -- -- -- *View-specific og:type:* -- -- You can override the default og:type inside the view by calling 'setOGType' inside the 'beforeRender' hook: -- -- > module JobSite.View.JobPositions.Show where -- > -- > instance View ShowView where -- > beforeRender ShowView { .. } = do -- > setOGType "mytype" -- > -- > html ShowView { .. } = [hsx|..|] ogTypeOrDefault :: (?context :: ControllerContext) => Text -> Html ogTypeOrDefault :: (?context::ControllerContext) => Text -> Html ogTypeOrDefault Text defaultValue = [hsx|<meta property="og:type" content={content}/>|] where content :: Text content = case forall value. (?context::ControllerContext, Typeable value) => Maybe value maybeFromFrozenContext @OGType of Just (OGType Text type_) -> Text type_ Maybe OGType Nothing -> Text defaultValue -- | Returns the meta og:description element. The og:description can be set using @setOGDescription "my description"@ from the view. -- -- You can use this inside your Layout like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitle}</title> -- > {ogDescriptionOrDefault "CO2 Database"} -- > </head> -- > |] -- -- -- *View-specific og:description:* -- -- You can override the default og:description inside the view by calling 'setOGDescription' inside the 'beforeRender' hook: -- -- > module JobSite.View.JobPositions.Show where -- > -- > instance View ShowView where -- > beforeRender ShowView { .. } = do -- > setOGDescription "The CO2 Footprint of beef is about 67kg CO2 per 1kg of beef." -- > -- > html ShowView { .. } = [hsx|..|] ogDescriptionOrDefault :: (?context :: ControllerContext) => Text -> Html ogDescriptionOrDefault :: (?context::ControllerContext) => Text -> Html ogDescriptionOrDefault Text defaultValue = [hsx|<meta property="og:description" content={content}/>|] where content :: Text content = case forall value. (?context::ControllerContext, Typeable value) => Maybe value maybeFromFrozenContext @OGDescription of Just (OGDescription Text description) -> Text description Maybe OGDescription Nothing -> Text defaultValue -- | Returns the meta og:url element if @setOGUrl "https://example.com/"@ was called before. -- -- You can use this inside your Layout like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitle}</title> -- > {ogUrl} -- > </head> -- > |] -- -- When 'setOGUrl' is not called, no meta tag will be rendered. -- -- *Setting og:url:* -- -- You can set the og:url inside the view by calling 'setOGUrl' inside the 'beforeRender' hook: -- -- > module JobSite.View.JobPositions.Show where -- > -- > instance View ShowView where -- > beforeRender ShowView { .. } = do -- > setOGUrl (urlTo ShowAction { .. }) -- > -- > html ShowView { .. } = [hsx|..|] ogUrl :: (?context :: ControllerContext) => Html ogUrl :: (?context::ControllerContext) => Html ogUrl = case forall value. (?context::ControllerContext, Typeable value) => Maybe value maybeFromFrozenContext @OGUrl of Just (OGUrl Text url) -> [hsx|<meta property="og:url" content={url}/>|] Maybe OGUrl Nothing -> Html forall a. Monoid a => a mempty -- | Returns the meta og:image element if @setOGImage "https://example.com/image.png"@ was called before. -- -- You can use this inside your Layout like this: -- -- > [hsx| -- > <head> -- > <title>{pageTitle}</title> -- > {ogImage} -- > </head> -- > |] -- -- When 'setOGImage' is not called, no meta tag will be rendered. -- -- *Setting og:image:* -- -- You can set the og:image inside the view by calling 'setOGImage' inside the 'beforeRender' hook: -- -- > module JobSite.View.JobPositions.Show where -- > -- > instance View ShowView where -- > beforeRender ShowView { .. } = do -- > setOGImage "https://example.com/image.png" -- > -- > html ShowView { .. } = [hsx|..|] ogImage :: (?context :: ControllerContext) => Html ogImage :: (?context::ControllerContext) => Html ogImage = case forall value. (?context::ControllerContext, Typeable value) => Maybe value maybeFromFrozenContext @OGImage of Just (OGImage Text url) -> [hsx|<meta property="og:image" content={url}/>|] Maybe OGImage Nothing -> Html forall a. Monoid a => a mempty