-
-
Notifications
You must be signed in to change notification settings - Fork 779
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Missing Title and Metadata (#2770)
* add document title to server spa meta * removed conflicting useMeta * replaced head with useMeta * formalized metadata injection * small injection refactor * added tests * added missing global tag * fixed setting tab title for logged-in users * simplified metadata update * remove duplicate tag and fix for foreign users * add metadata for shared recipes * added default recipe image * fixed shared URL --------- Co-authored-by: Kuchenpirat <[email protected]>
- Loading branch information
1 parent
2751e83
commit 1d1d61d
Showing
5 changed files
with
207 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" data-n-head="%7B%22lang%22:%7B%221%22:%22en%22%7D%7D"> | ||
<head> | ||
<meta data-n-head="1" data-hid="og:type" property="og:type" content="website"> | ||
<meta data-n-head="1" data-hid="og:title" property="og:title" content="Mealie"> | ||
<meta data-n-head="1" data-hid="og:site_name" property="og:site_name" content="Mealie"> | ||
<meta data-n-head="1" data-hid="og:description" property="og:description" content="Mealie is a recipe management app for your kitchen."> | ||
<meta data-n-head="1" data-hid="og:image" property="og:image" content="https://raw.githubusercontent.com/hay-kot/mealie/dev/frontend/public/img/icons/android-chrome-512x512.png"> | ||
<meta data-n-head="1" charset="utf-8"> | ||
<meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"> | ||
<meta data-n-head="1" data-hid="description" name="description" content="Mealie is a recipe management app for your kitchen."> | ||
<meta data-n-head="1" data-hid="charset" charset="utf-8"> | ||
<meta data-n-head="1" data-hid="mobile-web-app-capable" name="mobile-web-app-capable" content="yes"> | ||
<meta data-n-head="1" data-hid="apple-mobile-web-app-title" name="apple-mobile-web-app-title" content="Mealie"> | ||
<meta data-n-head="1" data-hid="theme-color" name="theme-color" content="#E58325"> | ||
<title>Mealie</title> | ||
<link data-n-head="1" data-hid="favicon" rel="icon" type="image/x-icon" href="/favicon.ico" data-n-head="ssr"> | ||
<link data-n-head="1" data-hid="shortcut icon" rel="shortcut icon" type="image/png" href="/icons/icon-x64.png" data-n-head="ssr"> | ||
<link data-n-head="1" data-hid="apple-touch-icon" rel="apple-touch-icon" type="image/png" href="/icons/apple-touch-icon.png" data-n-head="ssr"> | ||
<link data-n-head="1" data-hid="mask-icon" rel="mask-icon" href="/icons/safari-pinned-tab.svg" data-n-head="ssr"> | ||
<link data-n-head="1" rel="shortcut icon" href="/icons/android-chrome-192x192.png"> | ||
<link data-n-head="1" rel="apple-touch-icon" href="/icons/android-chrome-maskable-512x512.png" sizes="512x512"> | ||
<link data-n-head="1" rel="manifest" href="/_nuxt/manifest.260e8103.json" data-hid="manifest"> | ||
<base href="/"> | ||
<link rel="preload" href="/_nuxt/4134a9b.js" as="script"> | ||
<link rel="preload" href="/_nuxt/caa94a4.js" as="script"> | ||
<link rel="preload" href="/_nuxt/90b93a8.js" as="script"> | ||
<link rel="preload" href="/_nuxt/9da1d16.js" as="script"> | ||
</head> | ||
<body> | ||
<div id="__nuxt"> | ||
<style>#nuxt-loading{background:#fff;visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #000;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style> | ||
<script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script> | ||
<div id="nuxt-loading" aria-live="polite" role="status"> | ||
<div>Loading...</div> | ||
</div> | ||
</div> | ||
<script>window.__NUXT__=function(r,n,a,s,e,c,o){return{config:{GLOBAL_MIDDLEWARE:null,SUB_PATH:"",axios:{browserBaseURL:""},useDark:!1,themes:{dark:{primary:r,accent:n,secondary:a,success:s,info:e,warning:c,error:o,background:"#1E1E1E"},light:{primary:r,accent:n,secondary:a,success:s,info:e,warning:c,error:o}},_app:{basePath:"/",assetsPath:"/_nuxt/",cdnURL:null}}}}("#E58325","#007A99","#973542","#43A047","#1976d2","#FF6D00","#EF5350")</script> | ||
<script src="/_nuxt/4134a9b.js"></script><script src="/_nuxt/caa94a4.js"></script><script src="/_nuxt/90b93a8.js"></script><script src="/_nuxt/9da1d16.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
from bs4 import BeautifulSoup | ||
|
||
from mealie.routes.spa import MetaTag, inject_meta, inject_recipe_json | ||
from tests import data as test_data | ||
from tests.utils.factories import random_string | ||
|
||
|
||
def test_spa_metadata_injection(): | ||
fp = test_data.html_mealie_recipe | ||
with open(fp) as f: | ||
soup = BeautifulSoup(f, "lxml") | ||
assert soup.html and soup.html.head | ||
|
||
tags = soup.find_all("meta") | ||
assert tags | ||
|
||
title_tag = None | ||
for tag in tags: | ||
if tag.get("data-hid") == "og:title": | ||
title_tag = tag | ||
break | ||
|
||
assert title_tag and title_tag["content"] | ||
|
||
new_title_tag = MetaTag(hid="og:title", property_name="og:title", content=random_string()) | ||
new_arbitrary_tag = MetaTag(hid=random_string(), property_name=random_string(), content=random_string()) | ||
new_html = inject_meta(str(soup), [new_title_tag, new_arbitrary_tag]) | ||
|
||
# verify changes were injected | ||
soup = BeautifulSoup(new_html, "lxml") | ||
assert soup.html and soup.html.head | ||
|
||
tags = soup.find_all("meta") | ||
assert tags | ||
|
||
title_tag = None | ||
for tag in tags: | ||
if tag.get("data-hid") == "og:title": | ||
title_tag = tag | ||
break | ||
|
||
assert title_tag and title_tag["content"] == new_title_tag.content | ||
|
||
arbitrary_tag = None | ||
for tag in tags: | ||
if tag.get("data-hid") == new_arbitrary_tag.hid: | ||
arbitrary_tag = tag | ||
break | ||
|
||
assert arbitrary_tag and arbitrary_tag["content"] == new_arbitrary_tag.content | ||
|
||
|
||
def test_spa_recipe_json_injection(): | ||
recipe_name = random_string() | ||
schema = { | ||
"@context": "https://schema.org", | ||
"@type": "Recipe", | ||
"name": recipe_name, | ||
} | ||
|
||
fp = test_data.html_mealie_recipe | ||
with open(fp) as f: | ||
soup = BeautifulSoup(f, "lxml") | ||
assert "https://schema.org" not in str(soup) | ||
|
||
html = inject_recipe_json(str(soup), schema) | ||
|
||
assert "@context" in html | ||
assert "https://schema.org" in html | ||
assert recipe_name in html |