Enhance metadata handling in MetaTagHelper and views

Updated MetaTagHelper.cs to add new metadata properties including ArticlePublishedTime, MetaDescription, and others. Refactored JavaScript in Index1.cshtml for improved readability and added functionality for video playback. Updated metadata attributes in Index.cshtml and Index1.cshtml to support new properties, ensuring better SEO and social media sharing capabilities.
This commit is contained in:
Nick 2025-09-10 21:05:51 +01:00
parent 82cb5cde02
commit b3cc5ccedd
4 changed files with 220 additions and 122 deletions

View File

@ -8,27 +8,42 @@ namespace CatherineLynwood.TagHelpers
#region Public Properties
public DateTime? ArticleModifiedTime { get; set; }
public DateTime? ArticlePublishedTime { get; set; }
public string MetaAuthor { get; set; }
public string MetaDescription { get; set; }
public string MetaImage { get; set; }
public string MetaImageAlt { get; set; }
public string MetaImagePNG { get; set; }
public string MetaKeywords { get; set; }
public string MetaTitle { get; set; }
public string MetaUrl { get; set; }
public string OgSiteName { get; set; }
public string OgType { get; set; } = "article";
public string TwitterCardType { get; set; } = "summary_large_image";
public string TwitterCreatorHandle { get; set; }
public int? TwitterPlayerHeight { get; set; }
public int? TwitterPlayerWidth { get; set; }
public string TwitterSiteHandle { get; set; }
public string TwitterVideoUrl { get; set; }
#endregion
#endregion Public Properties
#region Public Methods
@ -63,6 +78,9 @@ namespace CatherineLynwood.TagHelpers
if (!string.IsNullOrWhiteSpace(MetaImage))
metaTags.AppendLine($"<meta property=\"og:image\" content=\"{MetaImage}\">");
if (!string.IsNullOrWhiteSpace(MetaImagePNG))
metaTags.AppendLine($"<meta property=\"og:image\" content=\"{MetaImagePNG}\">");
if (!string.IsNullOrWhiteSpace(MetaImageAlt))
metaTags.AppendLine($"<meta property=\"og:image:alt\" content=\"{MetaImageAlt}\">");
@ -124,6 +142,6 @@ namespace CatherineLynwood.TagHelpers
output.Content.SetHtmlContent(metaTags.ToString());
}
#endregion
#endregion Public Methods
}
}
}

View File

@ -399,38 +399,55 @@
<!-- Trailer source selection + play button -->
<script>
document.addEventListener("DOMContentLoaded", () => {
const vPortrait = document.getElementById("trailerPortrait");
const vLandscape = document.getElementById("trailerLandscape");
const playBtn = document.getElementById("trailerPlayBtn");
if (!playBtn) return;
document.addEventListener("DOMContentLoaded", () => {
const vPortrait = document.getElementById("trailerPortrait");
const vLandscape = document.getElementById("trailerLandscape");
const playBtn = document.getElementById("trailerPlayBtn");
if (!playBtn) return;
// Which video is currently visible according to Bootstraps lg breakpoint (>=992px)?
const isDesktop = () => window.matchMedia("(min-width: 992px)").matches;
const activeVideo = () => isDesktop() ? vLandscape : vPortrait;
// Which video is currently visible according to Bootstraps lg breakpoint (>=992px)?
const isDesktop = () => window.matchMedia("(min-width: 992px)").matches;
const activeVideo = () => isDesktop() ? vLandscape : vPortrait;
// Hide native controls when JS is active; custom button will start playback
[vPortrait, vLandscape].forEach(v => { if (v) v.controls = false; });
// Hide native controls when JS is active; custom button will start playback
[vPortrait, vLandscape].forEach(v => { if (v) v.controls = false; });
// Start playback on whichever video is visible
playBtn.addEventListener("click", () => {
const v = activeVideo();
if (!v) return;
v.muted = false;
v.volume = 1.0;
// Start playback on whichever video is visible
playBtn.addEventListener("click", () => {
const v = activeVideo();
if (!v) return;
v.muted = false;
v.volume = 1.0;
v.play().then(() => {
playBtn.style.display = "none";
}).catch(err => console.warn("Video play failed:", err));
});
// Toggle pause/play when user clicks on the video itself
[vPortrait, vLandscape].forEach(v => {
if (!v) return;
v.addEventListener("click", () => {
if (v.paused) {
v.play().then(() => {
playBtn.style.display = "none";
}).catch(err => console.warn("Video play failed:", err));
});
// If the user starts via OS overlay/natives, also hide the custom button
[vPortrait, vLandscape].forEach(v => {
if (!v) return;
v.addEventListener("play", () => { playBtn.style.display = "none"; }, { once: true });
});
});
} else {
v.pause();
playBtn.style.display = "block";
}
});
});
// If the user starts via OS overlay/natives, also hide the custom button
[vPortrait, vLandscape].forEach(v => {
if (!v) return;
v.addEventListener("play", () => { playBtn.style.display = "none"; });
v.addEventListener("pause", () => { playBtn.style.display = "block"; });
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const el = document.getElementById('fullSynopsis');
@ -532,112 +549,172 @@
<!-- Geo-based slug swap for /go/{retailer}-{format}-{country} + dev override -->
<script>
(function(){
// Direct IngramSpark URLs
const INGRAM_PB = "https://shop.ingramspark.com/b/084?params=6easpH54PaugzXFKdF4Tu4Izb0cvkMqbj3ZNlaYBKMJ";
const INGRAM_HB = "https://shop.ingramspark.com/b/084?params=GC1p1c8b66Rhfoy6Tq97SJmmhdZSEYuxBcCY5zxNstO";
(function(){
// Direct IngramSpark URLs
const INGRAM_PB = "https://shop.ingramspark.com/b/084?params=6easpH54PaugzXFKdF4Tu4Izb0cvkMqbj3ZNlaYBKMJ";
const INGRAM_HB = "https://shop.ingramspark.com/b/084?params=GC1p1c8b66Rhfoy6Tq97SJmmhdZSEYuxBcCY5zxNstO";
// Elements
const elKindle = document.getElementById('kindleLink');
const elPbSelf = document.getElementById('paperbackLinkSelf');
const elHbSelf = document.getElementById('hardbackLinkSelf');
const elPbAmazon = document.getElementById('paperbackLink'); // optional
const elHbAmazon = document.getElementById('hardbackLink'); // optional
const elHbNat = document.getElementById('hardbackNational');
const elPbNat = document.getElementById('paperbackNational');
// Elements
const elKindle = document.getElementById('kindleLink');
const elPbSelf = document.getElementById('paperbackLinkSelf');
const elHbSelf = document.getElementById('hardbackLinkSelf');
const elPbAmazon = document.getElementById('paperbackLink'); // optional
const elHbAmazon = document.getElementById('hardbackLink'); // optional
const elHbNat = document.getElementById('hardbackNational');
const elPbNat = document.getElementById('paperbackNational');
function show(el){ if (el) el.classList.remove('d-none'); }
function hide(el){ if (el) el.classList.add('d-none'); }
// Hint + flag
const elText = document.getElementById('buyCountryText');
const elFlag = document.getElementById('buyCountryFlag');
// helper to set both direct href and go slug
function setLink(el, directHref, slug) {
if (!el) return;
el.href = directHref;
el.setAttribute('data-go-slug', slug);
}
// Countries we show custom text + flag for
const targeted = new Set(['GB','US','CA','AU','IE']);
const countryNames = {
GB: 'United Kingdom',
US: 'United States',
CA: 'Canada',
AU: 'Australia',
IE: 'Ireland'
};
window.applyLinks = function applyLinks(code) {
const cc = (code || '').toUpperCase();
function show(el){ if (el) el.classList.remove('d-none'); }
function hide(el){ if (el) el.classList.add('d-none'); }
// Defaults to US Amazon
let kindleHref = "https://www.amazon.com/dp/B0FBS427VD";
let pbAmzHref = "https://www.amazon.com/dp/1068225815";
let hbAmzHref = "https://www.amazon.com/dp/1068225807";
// Set both the visible direct URL and the /go slug used by your click router
function setLink(el, directHref, slug) {
if (!el) return;
el.href = directHref;
el.setAttribute('data-go-slug', slug);
}
// National retailer defaults (GB Waterstones; US B&N)
let hbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225802";
let pbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225819";
let hbNatSlug = "waterstones-hardback-gb";
let pbNatSlug = "waterstones-paperback-gb";
function setHint(code, name) {
if (elText) elText.textContent = `Best options for ${name || 'your country'}`;
if (!elFlag) return;
const cc = (code || '').toUpperCase();
if (!cc) { elFlag.classList.add('d-none'); return; }
const base = `/images/flags/${cc}`;
elFlag.src = `${base}.svg`;
elFlag.alt = `${name || cc} flag`;
elFlag.classList.remove('d-none');
elFlag.onerror = function () {
if (this.src.endsWith('.svg')) this.src = `${base}.png`;
else this.classList.add('d-none');
};
}
switch (cc) {
case 'GB':
kindleHref = "https://www.amazon.co.uk/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.co.uk/dp/1068225815";
hbAmzHref = "https://www.amazon.co.uk/dp/1068225807";
hbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225802";
pbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225819";
hbNatSlug = "waterstones-hardback-gb";
pbNatSlug = "waterstones-paperback-gb";
break;
case 'US':
// keep US Amazon defaults
hbNatHref = "https://www.barnesandnoble.com/s/9781068225802";
pbNatHref = "https://www.barnesandnoble.com/s/9781068225819";
hbNatSlug = "bn-hardback-us";
pbNatSlug = "bn-paperback-us";
break;
case 'CA':
kindleHref = "https://www.amazon.ca/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.ca/dp/1068225815";
hbAmzHref = "https://www.amazon.ca/dp/1068225807";
// keep GB Waterstones/B&N as-is if you prefer not to show national links in CA
break;
case 'AU':
kindleHref = "https://www.amazon.com.au/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.com.au/dp/1068225815";
hbAmzHref = "https://www.amazon.com.au/dp/1068225807";
break;
case 'IE': // Ireland → use Amazon UK by default
kindleHref = "https://www.amazon.co.uk/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.co.uk/dp/1068225815";
hbAmzHref = "https://www.amazon.co.uk/dp/1068225807";
// keep Waterstones GB for national if you show it
hbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225802";
pbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225819";
hbNatSlug = "waterstones-hardback-gb";
pbNatSlug = "waterstones-paperback-gb";
break;
default:
break;
}
// Expose for reuse if needed elsewhere
window.applyLinks = function applyLinks(code) {
const cc = (code || '').toUpperCase();
// Kindle: direct Amazon, route via /go/ on click
setLink(elKindle, kindleHref, `amazon-kindle-${cc || 'us'}`);
// Defaults to US Amazon
let kindleHref = "https://www.amazon.com/dp/B0FBS427VD";
let pbAmzHref = "https://www.amazon.com/dp/1068225815";
let hbAmzHref = "https://www.amazon.com/dp/1068225807";
// Ingram “Self” buttons: direct Ingram in GB/US only; hide elsewhere
if (cc === 'GB' || cc === 'US') {
setLink(elPbSelf, INGRAM_PB, `ingram-paperback-${cc.toLowerCase()}`);
setLink(elHbSelf, INGRAM_HB, `ingram-hardback-${cc.toLowerCase()}`);
show(elPbSelf); show(elHbSelf);
} else {
hide(elPbSelf); hide(elHbSelf);
}
// National retailer defaults (GB Waterstones; US B&N)
let hbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225802";
let pbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225819";
let hbNatSlug = "waterstones-hardback-gb";
let pbNatSlug = "waterstones-paperback-gb";
// Amazon print buttons (if present): direct Amazon, route via /go/
setLink(elPbAmazon, pbAmzHref, `amazon-paperback-${cc || 'us'}`);
setLink(elHbAmazon, hbAmzHref, `amazon-hardback-${cc || 'us'}`);
switch (cc) {
case 'GB':
kindleHref = "https://www.amazon.co.uk/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.co.uk/dp/1068225815";
hbAmzHref = "https://www.amazon.co.uk/dp/1068225807";
hbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225802";
pbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225819";
hbNatSlug = "waterstones-hardback-gb";
pbNatSlug = "waterstones-paperback-gb";
break;
case 'US':
// keep US Amazon defaults
hbNatHref = "https://www.barnesandnoble.com/s/9781068225802";
pbNatHref = "https://www.barnesandnoble.com/s/9781068225819";
hbNatSlug = "bn-hardback-us";
pbNatSlug = "bn-paperback-us";
break;
case 'CA':
kindleHref = "https://www.amazon.ca/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.ca/dp/1068225815";
hbAmzHref = "https://www.amazon.ca/dp/1068225807";
break;
case 'AU':
kindleHref = "https://www.amazon.com.au/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.com.au/dp/1068225815";
hbAmzHref = "https://www.amazon.com.au/dp/1068225807";
break;
case 'IE': // Ireland → use Amazon UK by default
kindleHref = "https://www.amazon.co.uk/dp/B0FBS427VD";
pbAmzHref = "https://www.amazon.co.uk/dp/1068225815";
hbAmzHref = "https://www.amazon.co.uk/dp/1068225807";
hbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225802";
pbNatHref = "https://www.waterstones.com/book/the-alpha-flame/catherine-lynwood/9781068225819";
hbNatSlug = "waterstones-hardback-gb";
pbNatSlug = "waterstones-paperback-gb";
break;
default:
break;
}
// National retailer row: direct URLs, route via /go/
setLink(elHbNat, hbNatHref, hbNatSlug);
setLink(elPbNat, pbNatHref, pbNatSlug);
// Kindle: direct Amazon, route via /go/ on click
setLink(elKindle, kindleHref, `amazon-kindle-${cc || 'us'}`);
// Toggle any Ingram-only containers youve marked
document.querySelectorAll('[data-ingram-only="true"]').forEach(x => {
if (cc === 'GB' || cc === 'US') x.classList.remove('d-none'); else x.classList.add('d-none');
});
};
})();
// Ingram “Self” buttons: direct Ingram in GB/US only; hide elsewhere
if (cc === 'GB' || cc === 'US') {
setLink(elPbSelf, INGRAM_PB, `ingram-paperback-${cc.toLowerCase()}`);
setLink(elHbSelf, INGRAM_HB, `ingram-hardback-${cc.toLowerCase()}`);
show(elPbSelf); show(elHbSelf);
} else {
hide(elPbSelf); hide(elHbSelf);
}
// Amazon print buttons (if present): direct Amazon, route via /go/
setLink(elPbAmazon, pbAmzHref, `amazon-paperback-${cc.toLowerCase() || 'us'}`);
setLink(elHbAmazon, hbAmzHref, `amazon-hardback-${cc.toLowerCase() || 'us'}`);
// National retailer row: direct URLs, route via /go/
setLink(elHbNat, hbNatHref, hbNatSlug);
setLink(elPbNat, pbNatHref, pbNatSlug);
// Toggle any Ingram-only containers youve marked
document.querySelectorAll('[data-ingram-only="true"]').forEach(x => {
if (cc === 'GB' || cc === 'US') x.classList.remove('d-none'); else x.classList.add('d-none');
});
};
function updateForCountry(code, nameFromAPI) {
const cc = (code || '').toUpperCase();
// Update links
window.applyLinks(cc);
// Update hint + flag only for targeted set; leave default text for others
if (targeted.has(cc)) {
setHint(cc, countryNames[cc] || nameFromAPI || cc);
}
}
// Dev override: ?country=CA
const params = new URLSearchParams(location.search);
const override = params.get('country');
if (override) {
const cc = override.toUpperCase();
updateForCountry(cc, countryNames[cc] || cc);
return;
}
// Single geo lookup
fetch('https://ipapi.co/json/')
.then(r => r.json())
.then(d => {
const code = d && d.country_code ? String(d.country_code).toUpperCase() : '';
const name = d && d.country_name ? d.country_name : code;
updateForCountry(code, name);
})
.catch(() => {
// Leave defaults if geo fails
window.applyLinks('');
});
})();
</script>
@ -650,6 +727,7 @@
meta-author="Catherine Lynwood"
meta-url="https://www.catherinelynwood.com/the-alpha-flame/discovery"
meta-image="https://www.catherinelynwood.com/images/webp/the-alpha-flame-discovery-cover-1200.webp"
meta-image-png="https://www.catherinelynwood.com/images/the-alpha-flame-discovery-cover.png"
meta-image-alt="Maggie from 'The Alpha Flame: Discovery' by Catherine Lynwood"
og-site-name="Catherine Lynwood - The Alpha Flame: Discovery"
article-published-time="@new DateTime(2024, 11, 20)"

View File

@ -72,6 +72,7 @@
meta-author="Catherine Lynwood"
meta-url="https://www.catherinelynwood.com/"
meta-image="https://www.catherinelynwood.com/images/webp/the-alpha-flame-discovery-cover-600.webp"
meta-image-png="https://www.catherinelynwood.com/images/the-alpha-flame-discovery-cover.png"
meta-image-alt="Cover artwork from 'The Alpha Flame: Discovery' by Catherine Lynwood"
og-site-name="Catherine Lynwood The Alpha Flame"
article-published-time="@new DateTime(2024, 11, 20)"

View File

@ -162,7 +162,8 @@
meta-keywords="The Alpha Flame trilogy, Catherine Lynwood, 1980s fiction, family saga, twin sisters, Birmingham novel, suspense fiction, indie fiction series"
meta-author="Catherine Lynwood"
meta-url="https://www.catherinelynwood.com/the-alpha-flame"
meta-image="https://www.catherinelynwood.com/images/webp/the-alpha-flame-trilogy-banner.webp"
meta-image="https://www.catherinelynwood.com/images/webp/the-alpha-flame-discovery-cover-1200.webp"
meta-image-png="https://www.catherinelynwood.com/images/the-alpha-flame-discovery-cover.png"
meta-image-alt="The Alpha Flame trilogy banner image showing three covers of the series by Catherine Lynwood"
og-site-name="Catherine Lynwood - The Alpha Flame Trilogy"
article-published-time="@new DateTime(2024, 11, 20)"