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" <>)