Feat/ghost integration #1
@@ -51,3 +51,4 @@ pnpm-debug.log*
|
|||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
|
|
||||||
.vercel
|
.vercel
|
||||||
|
.env*.local
|
||||||
|
|||||||
Submodule
+1
Submodule CampaignX_Sigil added at 2a984adfb3
@@ -31,16 +31,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="../../index.html#product">Product</a>
|
<a href="../../index.html#product">Product</a>
|
||||||
@@ -272,11 +263,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
@@ -10,16 +10,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="../../index.html#product">Product</a>
|
<a href="../../index.html#product">Product</a>
|
||||||
@@ -191,11 +182,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
@@ -31,16 +31,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="../../index.html#product">Product</a>
|
<a href="../../index.html#product">Product</a>
|
||||||
@@ -273,11 +264,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
+2
-15
@@ -22,16 +22,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="../index.html#product">Product</a>
|
<a href="../index.html#product">Product</a>
|
||||||
@@ -193,11 +184,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
@@ -31,16 +31,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="../../index.html#product">Product</a>
|
<a href="../../index.html#product">Product</a>
|
||||||
@@ -271,11 +262,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
@@ -37,16 +37,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="./index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="./index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="./img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="./index.html#product">Product</a>
|
<a href="./index.html#product">Product</a>
|
||||||
@@ -579,11 +570,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="./index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="./index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="./img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
+2
-15
@@ -53,16 +53,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="#top" aria-label="LynkedUp Pro home">
|
<a class="logo" href="#top" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="./img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="#product">Product</a>
|
<a href="#product">Product</a>
|
||||||
@@ -1227,11 +1218,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="#top" aria-label="LynkedUp Pro home">
|
<a class="logo" href="#top" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="./img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
+52
-6
@@ -27,6 +27,40 @@ function truncate(text: string, max: number): string {
|
|||||||
return `${cut.slice(0, lastSpace > 0 ? lastSpace : max).trimEnd()}…`;
|
return `${cut.slice(0, lastSpace > 0 ? lastSpace : max).trimEnd()}…`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upgrades a Ghost-hosted `http://` URL to `https://`.
|
||||||
|
*
|
||||||
|
* Ghost builds asset URLs from its own configured `url` setting. If that is set
|
||||||
|
* to http (as api.lynkedup.dev currently is), every image comes back insecure and
|
||||||
|
* browsers block it as mixed content on our HTTPS pages — silently, before the
|
||||||
|
* server's 301 to https can help.
|
||||||
|
*
|
||||||
|
* Only the configured Ghost host is upgraded: an arbitrary external http image in
|
||||||
|
* post content may genuinely have no https, and forcing it would break it.
|
||||||
|
*/
|
||||||
|
export function secureGhostUrl(url: string | null, ghostHost: string): string | null {
|
||||||
|
if (!url || !url.startsWith("http://")) return url;
|
||||||
|
try {
|
||||||
|
const parsed = new URL(url);
|
||||||
|
if (parsed.host !== ghostHost) return url;
|
||||||
|
parsed.protocol = "https:";
|
||||||
|
return parsed.toString();
|
||||||
|
} catch {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Applies {@link secureGhostUrl} to src/srcset/href attributes inside post HTML. */
|
||||||
|
function secureHtmlUrls(html: string, ghostHost: string): string {
|
||||||
|
return html.replace(
|
||||||
|
/(\s(?:src|href)=")(http:\/\/[^"]+)(")/gi,
|
||||||
|
(match, pre: string, url: string, post: string) => {
|
||||||
|
const secure = secureGhostUrl(url, ghostHost);
|
||||||
|
return secure ? `${pre}${secure}${post}` : match;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewrites a Ghost image URL to a resized variant. Ghost serves derivatives from
|
* Rewrites a Ghost image URL to a resized variant. Ghost serves derivatives from
|
||||||
* `/content/images/size/w<width>/...`; any non-Ghost or already-sized URL is
|
* `/content/images/size/w<width>/...`; any non-Ghost or already-sized URL is
|
||||||
@@ -77,12 +111,13 @@ function resolveExcerpt(post: GhostPost, plain: string): string {
|
|||||||
function resolveSeo(
|
function resolveSeo(
|
||||||
post: GhostPost,
|
post: GhostPost,
|
||||||
config: GhostConfig,
|
config: GhostConfig,
|
||||||
|
ghostHost: string,
|
||||||
title: string,
|
title: string,
|
||||||
excerpt: string
|
excerpt: string
|
||||||
): PostSeo {
|
): PostSeo {
|
||||||
const metaTitle = post.meta_title?.trim() || `${title} - LynkedUp Pro Blog`;
|
const metaTitle = post.meta_title?.trim() || `${title} - LynkedUp Pro Blog`;
|
||||||
const metaDescription = post.meta_description?.trim() || excerpt;
|
const metaDescription = post.meta_description?.trim() || excerpt;
|
||||||
const ogImage = ghostImage(post.og_image || post.feature_image, 1200);
|
const ogImage = secureGhostUrl(ghostImage(post.og_image || post.feature_image, 1200), ghostHost);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
metaTitle,
|
metaTitle,
|
||||||
@@ -92,7 +127,7 @@ function resolveSeo(
|
|||||||
ogImage,
|
ogImage,
|
||||||
twitterTitle: post.twitter_title?.trim() || metaTitle,
|
twitterTitle: post.twitter_title?.trim() || metaTitle,
|
||||||
twitterDescription: post.twitter_description?.trim() || metaDescription,
|
twitterDescription: post.twitter_description?.trim() || metaDescription,
|
||||||
twitterImage: ghostImage(post.twitter_image, 1200) || ogImage,
|
twitterImage: secureGhostUrl(ghostImage(post.twitter_image, 1200), ghostHost) || ogImage,
|
||||||
// Ghost's canonical_url wins when an editor has set one (e.g. syndicated
|
// Ghost's canonical_url wins when an editor has set one (e.g. syndicated
|
||||||
// posts); otherwise the canonical is this site's own URL for the slug.
|
// posts); otherwise the canonical is this site's own URL for the slug.
|
||||||
canonicalUrl: post.canonical_url?.trim() || `${config.siteUrl}/blog/${post.slug}/`,
|
canonicalUrl: post.canonical_url?.trim() || `${config.siteUrl}/blog/${post.slug}/`,
|
||||||
@@ -106,9 +141,20 @@ const DATE_FORMAT = new Intl.DateTimeFormat("en-US", {
|
|||||||
timeZone: "UTC",
|
timeZone: "UTC",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** The Ghost host (e.g. "api.lynkedup.dev"), for upgrading its http asset URLs. */
|
||||||
|
function ghostHostFrom(config: GhostConfig): string {
|
||||||
|
try {
|
||||||
|
return new URL(config.apiUrl).host;
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function normalizePost(post: GhostPost, config: GhostConfig): BlogPost {
|
export function normalizePost(post: GhostPost, config: GhostConfig): BlogPost {
|
||||||
const html = post.html ?? "";
|
const ghostHost = ghostHostFrom(config);
|
||||||
const plain = toPlainText(html);
|
const rawHtml = post.html ?? "";
|
||||||
|
const html = secureHtmlUrls(rawHtml, ghostHost);
|
||||||
|
const plain = toPlainText(rawHtml);
|
||||||
const title = post.title?.trim() || "Untitled";
|
const title = post.title?.trim() || "Untitled";
|
||||||
const excerpt = resolveExcerpt(post, plain);
|
const excerpt = resolveExcerpt(post, plain);
|
||||||
const tags = resolveTags(post);
|
const tags = resolveTags(post);
|
||||||
@@ -120,7 +166,7 @@ export function normalizePost(post: GhostPost, config: GhostConfig): BlogPost {
|
|||||||
title,
|
title,
|
||||||
html,
|
html,
|
||||||
excerpt,
|
excerpt,
|
||||||
featureImage: post.feature_image,
|
featureImage: secureGhostUrl(post.feature_image, ghostHost),
|
||||||
featureImageAlt: post.feature_image_alt?.trim() || title,
|
featureImageAlt: post.feature_image_alt?.trim() || title,
|
||||||
author: resolveAuthor(post),
|
author: resolveAuthor(post),
|
||||||
publishedAt: validDate,
|
publishedAt: validDate,
|
||||||
@@ -129,7 +175,7 @@ export function normalizePost(post: GhostPost, config: GhostConfig): BlogPost {
|
|||||||
readingTime: resolveReadingTime(post, plain),
|
readingTime: resolveReadingTime(post, plain),
|
||||||
tags,
|
tags,
|
||||||
primaryTagLabel: (tags[0]?.name || "Field notes").toUpperCase(),
|
primaryTagLabel: (tags[0]?.name || "Field notes").toUpperCase(),
|
||||||
seo: resolveSeo(post, config, title, excerpt),
|
seo: resolveSeo(post, config, ghostHost, title, excerpt),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -91,8 +91,8 @@
|
|||||||
}
|
}
|
||||||
.nav{display:flex;align-items:center;gap:28px;height:60px}
|
.nav{display:flex;align-items:center;gap:28px;height:60px}
|
||||||
.logo{display:flex;align-items:center;gap:10px;font-weight:700;font-size:17px;letter-spacing:-.01em}
|
.logo{display:flex;align-items:center;gap:10px;font-weight:700;font-size:17px;letter-spacing:-.01em}
|
||||||
.logo svg{width:24px;height:24px}
|
/* Wordmark lockup (195x42): fix the height and let width follow the aspect ratio. */
|
||||||
.logo span b{color:var(--amber);font-weight:700}
|
.logo img{height:26px;width:auto;display:block}
|
||||||
.nav-links{display:flex;gap:26px;margin-left:auto}
|
.nav-links{display:flex;gap:26px;margin-left:auto}
|
||||||
.nav-links a{font-size:14px;color:var(--dim);transition:color .12s ease;position:relative}
|
.nav-links a{font-size:14px;color:var(--dim);transition:color .12s ease;position:relative}
|
||||||
.nav-links a::before{
|
.nav-links a::before{
|
||||||
|
|||||||
+2
-15
@@ -22,16 +22,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="wrap nav">
|
<div class="wrap nav">
|
||||||
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<defs>
|
|
||||||
<linearGradient id="lgA" x1="0" y1="0" x2="1" y2="1">
|
|
||||||
<stop offset="0" stop-color="#5BD9EE"/><stop offset="1" stop-color="#1B7E9B"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="url(#lgA)" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<nav class="nav-links" aria-label="Primary">
|
<nav class="nav-links" aria-label="Primary">
|
||||||
<a href="../index.html#product">Product</a>
|
<a href="../index.html#product">Product</a>
|
||||||
@@ -309,11 +300,7 @@
|
|||||||
<div class="foot-grid">
|
<div class="foot-grid">
|
||||||
<div class="foot-col brand">
|
<div class="foot-col brand">
|
||||||
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
<a class="logo" href="../index.html" aria-label="LynkedUp Pro home">
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<img src="../img/lynkedup-logo.png" alt="" width="195" height="42" decoding="async">
|
||||||
<path d="M8.8 5.6 3.4 8.75v6.5L8.8 18.4l5.4-3.15v-6.5Z" stroke="#17607A" stroke-width="1.7"/>
|
|
||||||
<path d="M15.2 5.6 9.8 8.75v6.5l5.4 3.15 5.4-3.15v-6.5Z" stroke="#2EC5DD" stroke-width="1.7"/>
|
|
||||||
</svg>
|
|
||||||
<span>LynkedUp <b>Pro</b></span>
|
|
||||||
</a>
|
</a>
|
||||||
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
<p class="foot-tag">The construction CRM that does the paperwork.</p>
|
||||||
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
<span class="tag">16990 Dallas Pkwy, Suite 206<br>Dallas, TX 75248<br>(866) 259-6533<br>Info@LynkedUpPro.com</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user