diff --git a/docs/guide/feed.md b/docs/guide/feed.md index 432e10bc1..6ae94c856 100644 --- a/docs/guide/feed.md +++ b/docs/guide/feed.md @@ -17,8 +17,8 @@ path:blog/* If the note is named `blog.md`, then the feed will be available at `blog.xml`. -> [!note] `feed.siteUrl` -> You must set `feed.siteUrl` (see below) in the [[yaml-config|index.yaml]] for the feed to be generated. +> [!note] `page.siteUrl` +> You must set `page.siteUrl` (see below) in the [[yaml-config|index.yaml]] for the feed to be generated. ## Example @@ -28,7 +28,6 @@ An example is available in the [[query]] note. You can access its feed at [query Here are the supported settings: -- `feed.siteUrl`: the site url, default to global setting from the [[yaml-config|index.yaml]]. - `feed.title`: the feed title, default to the note title. - `feed.limit`: the maximum number of notes to include in the feed. diff --git a/docs/guide/html-template/ogp.md b/docs/guide/html-template/ogp.md index cd256596d..94476a2df 100644 --- a/docs/guide/html-template/ogp.md +++ b/docs/guide/html-template/ogp.md @@ -18,6 +18,10 @@ Emanote generates OGP meta tags for each note, using the following rules: | `og:type` | `website` | | `og:image` | The first image[^img] in the note, if any; otherwise, use the `image` [[yaml-config\|YAML metadata]] | +## Twitter + +[Twitter Card](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards) style can be set using `page.twitter.card` [[yaml-config|YAML metadata]]. It it set to `summary_large_image` by default. + [^wl]: Wikilinks like `[[foo]]` render *as is* (due to a limitation). However, `[[foo|some text]]` will render as `some text` (the link text). If you do not wish to have wikilink syntax appearing in page description, specify a custom like in the second example. [^img]: Unfortunately, embed wikilinks (eg.: `![[foo.jpeg]]`) are not recognized here. You should use regular links, eg.: `![](foo.jpeg)`. \ No newline at end of file diff --git a/docs/guide/yaml-config.md b/docs/guide/yaml-config.md index 01d325ddb..246e61833 100644 --- a/docs/guide/yaml-config.md +++ b/docs/guide/yaml-config.md @@ -17,6 +17,10 @@ Notice how this page's sidebar colorscheme has [changed to green]{.greenery}? Vi >[!tip] Using in HTML templates > You can reference the YAML frontmatter config from [[html-template]]. See [here](https://github.com/srid/emanote/discussions/131#discussioncomment-1382189) for details. +## Special properties + +- `page.image`: The image to use for the page. This is used for the [[ogp]] meta tag `og:image` meta tag. If not specified, the first image in the page is used. Relative URLs are automatically rewritten to absolute URLs if `page.siteUrl` is non-empty. + ## Examples diff --git a/docs/index.yaml b/docs/index.yaml index 426c7b31b..6212be834 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -2,9 +2,7 @@ template: urlStrategy: pretty page: + siteUrl: https://emanote.srid.ca siteTitle: Emanote headHtml: | - -feed: - siteUrl: https://emanote.srid.ca diff --git a/emanote/CHANGELOG.md b/emanote/CHANGELOG.md index 4cb1154e7..393a46354 100644 --- a/emanote/CHANGELOG.md +++ b/emanote/CHANGELOG.md @@ -13,6 +13,7 @@ - Allow specifying `lang` attribute for HTML page in YAML config ([\#485](https://github.com/srid/emanote/pull/485)) - KaTeX support ([\#489](https://github.com/srid/emanote/pull/489)) - Lua filters: filter paths will now be looked up in all layers now. + - **BACKWARDS INCOMPTABILE**: `feed.siteUrl` is now `page.siteUrl` - Bug fixes: - Emanote no longer crashes when run on an empty directory ([\#487](https://github.com/srid/emanote/issues/487)) - Stork search fixes diff --git a/emanote/default/index.yaml b/emanote/default/index.yaml index 88b87ca0a..0aea0c693 100644 --- a/emanote/default/index.yaml +++ b/emanote/default/index.yaml @@ -69,6 +69,9 @@ pandoc: # Put page-specific metadata here. Override them in Markdown frontmatter or # per-folder YAML as necessary. page: + # The URL to the deployed site. Must include everything upto `baseUrl` above. + siteUrl: "" + siteTitle: My Emanote Site # Desription is expected to be set on a per-page basis. # By default, the first paragraph is used for description. @@ -85,6 +88,9 @@ page: # Used for https://ogp.me/ image: "" + twitter: + card: summary_large_image + # Put anything that should go in of these routes here: # You can reference other metadata keys using # Or use the JS behaviour library below. diff --git a/emanote/default/templates/base.tpl b/emanote/default/templates/base.tpl index c55e189e2..719ab46ac 100644 --- a/emanote/default/templates/base.tpl +++ b/emanote/default/templates/base.tpl @@ -19,6 +19,9 @@ + + + diff --git a/emanote/emanote.cabal b/emanote/emanote.cabal index df803d651..23521bea7 100644 --- a/emanote/emanote.cabal +++ b/emanote/emanote.cabal @@ -1,6 +1,6 @@ cabal-version: 2.4 name: emanote -version: 1.3.7.0 +version: 1.3.8.0 license: AGPL-3.0-only copyright: 2022 Sridhar Ratnakumar maintainer: srid@srid.ca diff --git a/emanote/src/Emanote/Model/SData.hs b/emanote/src/Emanote/Model/SData.hs index f67b4c5a4..acbf2c4f5 100644 --- a/emanote/src/Emanote/Model/SData.hs +++ b/emanote/src/Emanote/Model/SData.hs @@ -66,6 +66,22 @@ lookupAeson x (k :| ks) meta = Aeson.Error _ -> Nothing Aeson.Success b -> pure b +-- | Modify a key inside the aeson Value +modifyAeson :: NonEmpty KM.Key -> (Maybe Aeson.Value -> Maybe Aeson.Value) -> Aeson.Value -> Aeson.Value +modifyAeson (k :| ks) f meta = + case nonEmpty ks of + Nothing -> + withObject meta $ \obj -> + runIdentity $ KM.alterF (pure . f) k obj + Just ks' -> + withObject meta $ \obj -> + runIdentity $ KM.alterF @Identity (\mv -> Identity $ modifyAeson ks' f <$> mv) k obj + where + withObject :: Aeson.Value -> (Aeson.Object -> Aeson.Object) -> Aeson.Value + withObject v g = case v of + Aeson.Object x -> Aeson.Object $ g x + x -> x + oneAesonText :: [Text] -> Text -> Aeson.Value oneAesonText k v = case nonEmpty k of diff --git a/emanote/src/Emanote/View/Feed.hs b/emanote/src/Emanote/View/Feed.hs index 9a591245c..24cc885f1 100644 --- a/emanote/src/Emanote/View/Feed.hs +++ b/emanote/src/Emanote/View/Feed.hs @@ -81,8 +81,8 @@ renderFeed model baseNote = case eFeedText of let feedMeta :: Aeson.Value feedMeta = getEffectiveRouteMeta (_noteRoute baseNote) model let mFeedUrl :: Maybe Text - mFeedUrl = lookupAeson Nothing ("feed" :| ["siteUrl"]) feedMeta - feedUrl <- maybeToRight "index.yaml or note doesn't have feed.siteUrl" mFeedUrl + mFeedUrl = lookupAeson Nothing ("page" :| ["siteUrl"]) feedMeta + feedUrl <- maybeToRight "index.yaml or note doesn't have page.siteUrl" mFeedUrl -- process the notes let noteUrl note = diff --git a/emanote/src/Emanote/View/Template.hs b/emanote/src/Emanote/View/Template.hs index 45f641bd6..aa3809d39 100644 --- a/emanote/src/Emanote/View/Template.hs +++ b/emanote/src/Emanote/View/Template.hs @@ -128,10 +128,26 @@ loaderHead :: LByteString loaderHead = "Union mounting notebook layers; please wait ..." +patchMeta :: Aeson.Value -> Aeson.Value +patchMeta meta = + -- Convert relative to absolute URLs in "page.image", because some sites + -- (Twitter) require "og:image" to be absolute. + SData.modifyAeson + ("page" :| ["image"]) + ( \case + Just (Aeson.String v) + | not (":" `T.isInfixOf` v) && siteUrl /= "" -> + Just $ Aeson.String $ siteUrl <> "/" <> v + x -> x + ) + meta + where + siteUrl = SData.lookupAeson @Text "" ("page" :| ["siteUrl"]) meta + renderLmlHtml :: Model -> MN.Note -> LByteString renderLmlHtml model note = do let r = note ^. MN.noteRoute - meta = Meta.getEffectiveRouteMetaWith (note ^. MN.noteMeta) r model + meta = patchMeta $ Meta.getEffectiveRouteMetaWith (note ^. MN.noteMeta) r model -- Force a doctype into the generated HTML as a workaround for Heist -- discarding it. See: https://github.com/srid/emanote/issues/216 withDoctype = ("\n" <>)