From 099469be395710764bcdca8e423f063d93626dd4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juhamatti=20Niemel=C3=A4?= <iiska@iki.fi>
Date: Wed, 17 Oct 2018 20:11:12 +0300
Subject: [PATCH] Open Graph Protocol metadata for version pages

Renders OGP metadata for package documentation pages which could be used
to enable prettier rendering of Elm package links when shared at social
sites, chat rooms and forums.

For example `elm/http` would have following metadata section:

```html
<meta property="og:site_name" content="Elm Packages">
<meta property="og:title" content="elm/http 1.0.0">
<meta property="og:image" content="https://package.elm-lang.org/assets/elm_logo.svg">
<meta property="og:description" content="Make HTTP requests">
```

Could resolve #236.
---
 assets/elm_logo.svg      | 39 +++++++++++++++++++++++++++++++++++++++
 src/backend/Main.hs      |  7 ++++---
 src/backend/ServeFile.hs | 39 ++++++++++++++++++++++++++++++++-------
 3 files changed, 75 insertions(+), 10 deletions(-)
 create mode 100644 assets/elm_logo.svg

diff --git a/assets/elm_logo.svg b/assets/elm_logo.svg
new file mode 100644
index 00000000..7d669f0a
--- /dev/null
+++ b/assets/elm_logo.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+   viewBox="0 0 323.141 322.95" enable-background="new 0 0 323.141 322.95" xml:space="preserve">
+<g>
+  <polygon
+    fill="#F0AD00"
+    points="161.649,152.782 231.514,82.916 91.783,82.916"/>
+
+  <polygon
+    fill="#7FD13B"
+    points="8.867,0 79.241,70.375 232.213,70.375 161.838,0"/>
+
+  <rect
+    fill="#7FD13B"
+    x="192.99"
+    y="107.392"
+    transform="matrix(0.7071 0.7071 -0.7071 0.7071 186.4727 -127.2386)"
+    width="107.676"
+    height="108.167"/>
+
+  <polygon
+    fill="#60B5CC"
+    points="323.298,143.724 323.298,0 179.573,0"/>
+
+  <polygon
+    fill="#5A6378"
+    points="152.781,161.649 0,8.868 0,314.432"/>
+
+  <polygon
+    fill="#F0AD00"
+    points="255.522,246.655 323.298,314.432 323.298,178.879"/>
+
+  <polygon
+    fill="#60B5CC"
+    points="161.649,170.517 8.869,323.298 314.43,323.298"/>
+</g>
+</svg>
diff --git a/src/backend/Main.hs b/src/backend/Main.hs
index e10eb8c9..39037d76 100644
--- a/src/backend/Main.hs
+++ b/src/backend/Main.hs
@@ -187,7 +187,7 @@ serveVersion memory author project maybeVersion info =
         Nothing ->
           S.pass
 
-        Just (Memory.Summary versions _ _) ->
+        Just (Memory.Summary versions maybeDetails _) ->
           case verifyVersion maybeVersion versions of
             Nothing ->
               S.pass
@@ -195,7 +195,8 @@ serveVersion memory author project maybeVersion info =
             Just version ->
               case info of
                 Readme ->
-                  ServeFile.version name version Nothing
+                  ServeFile.version name version Nothing $
+                    maybe Nothing (Just . fst) maybeDetails
 
                 Module asset ->
                   serveVersionHelp name version asset
@@ -220,7 +221,7 @@ serveVersionHelp name version asset =
     _ ->
       case Module.fromHyphenPath asset of
         Just moduleName ->
-          ServeFile.version name version (Just moduleName)
+          ServeFile.version name version (Just moduleName) Nothing
 
         Nothing ->
           S.pass
diff --git a/src/backend/ServeFile.hs b/src/backend/ServeFile.hs
index 82225444..8a8e47ec 100644
--- a/src/backend/ServeFile.hs
+++ b/src/backend/ServeFile.hs
@@ -28,7 +28,7 @@ import qualified Elm.Package as Pkg
 
 misc :: B.Builder -> Snap ()
 misc title =
-  makeHtml title mempty
+  makeHtml title mempty (makeOgpMetadata title Nothing)
 
 
 
@@ -37,15 +37,18 @@ misc title =
 
 project :: Pkg.Name -> Snap ()
 project pkg =
-  makeHtml (B.stringUtf8 (Pkg.toString pkg)) mempty
+  let
+    title = (B.stringUtf8 (Pkg.toString pkg))
+  in
+  makeHtml title mempty (makeOgpMetadata title Nothing)
 
 
 
 -- VERSION
 
 
-version :: Pkg.Name -> Pkg.Version -> Maybe Module.Raw -> Snap ()
-version pkg@(Pkg.Name _ prjct) vsn maybeName =
+version :: Pkg.Name -> Pkg.Version -> Maybe Module.Raw -> Maybe Text.Text -> Snap ()
+version pkg@(Pkg.Name _ prjct) vsn maybeName maybeDescription =
   let
     versionString =
       Pkg.versionToString vsn
@@ -56,8 +59,14 @@ version pkg@(Pkg.Name _ prjct) vsn maybeName =
     title =
       maybe "" (++" - ") maybeStringName
       ++ Text.unpack prjct ++ " " ++ versionString
+
+    ogpTitle =
+      maybe "" (++" - ") maybeStringName
+      ++ Pkg.toString pkg ++ " " ++ versionString
+
   in
   makeHtml (B.stringUtf8 title) (makeCanonicalLink pkg maybeName)
+    (makeOgpMetadata (B.stringUtf8 ogpTitle) maybeDescription)
 
 
 
@@ -106,19 +115,35 @@ renames =
   (,)
 
 
+-- OGP METADATA
+
+makeOgpMetadata :: B.Builder -> Maybe Text.Text -> B.Builder
+makeOgpMetadata title maybeDescription =
+  let
+    description =
+      maybe "" (B.stringUtf8 . Text.unpack . \d ->
+          [r|<meta property="og:description" content="|] <> d <> [r|">|]
+        ) maybeDescription
+  in
+  [r|<meta property="og:type" content="website">
+  <meta property="og:site_name" content="Elm Packages">
+  <meta property="og:title" content="|] <> title <> [r|">
+  <meta property="og:image" content="http://localhost:8080/assets/elm_logo.svg">|]
+    <> description
+
 
 -- SKELETON
 
 
-makeHtml :: B.Builder -> B.Builder -> Snap ()
-makeHtml title canonicalLink =
+makeHtml :: B.Builder -> B.Builder -> B.Builder -> Snap ()
+makeHtml title canonicalLink ogpMetadata =
   writeBuilder $
     [r|<!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="UTF-8">
   <link rel="shortcut icon" size="16x16, 32x32, 48x48, 64x64, 128x128, 256x256" href="/assets/favicon.ico">
-  <title>|] <> title <> [r|</title>|] <> canonicalLink <> [r|
+  <title>|] <> title <> [r|</title>|] <> canonicalLink <> ogpMetadata <> [r|
   <link rel="stylesheet" href="/assets/highlight/styles/default.css?|] <> uniqueToken <> [r|">
   <link rel="stylesheet" href="/assets/style.css?|] <> uniqueToken <> [r|">
   <script src="/assets/highlight/highlight.pack.js?|] <> uniqueToken <> [r|"></script>