dh-remixer-sdk 0.0.29 → 0.0.30-1711bcb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var botPattern =
|
|
2
|
+
"(googlebot|bot|bingbot|slurp|DuckDuckBot|baiduspider|yandexbot|facebookexternalhit|twitterbot|linkedinbot|pinterest|slackbot|discordbot|whatsapp|telegrambot|embedly|quora link preview|applebot|semrushbot|ahrefsbot|mj12bot|dotbot)";
|
|
3
|
+
var re = new RegExp(botPattern, "i");
|
|
4
|
+
var ua = navigator.userAgent;
|
|
5
|
+
|
|
6
|
+
if (!re.test(ua)) {
|
|
7
|
+
import("%BUNDLE_PATH%");
|
|
8
|
+
}
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
parseHtmlForContactInfo,
|
|
23
23
|
applyBusinessLdJson,
|
|
24
24
|
} from "./parse-html-for-contact-info.mjs";
|
|
25
|
+
import { injectBundleWrapper } from "./inject-bundle-wrapper.mjs";
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Handles:
|
|
@@ -31,6 +32,8 @@ import {
|
|
|
31
32
|
*/
|
|
32
33
|
|
|
33
34
|
async function main() {
|
|
35
|
+
await injectBundleWrapper();
|
|
36
|
+
|
|
34
37
|
const visistedRoutes = [];
|
|
35
38
|
let queuedRoutes = [ROOT_ROUTE];
|
|
36
39
|
const reactRoutes = await getRoutes();
|
|
@@ -90,9 +93,6 @@ Sitemap: https://${TARGET_DOMAIN}/sitemap.xml
|
|
|
90
93
|
);
|
|
91
94
|
console.log("[created] robots.txt");
|
|
92
95
|
|
|
93
|
-
// Build succeeded: drop the hidden SPA-bootstrap sidecar so it never ships
|
|
94
|
-
// in the deployed output. (On a crash we skip this and leave it behind so a
|
|
95
|
-
// re-run can recover the clobbered index.html.)
|
|
96
96
|
await prerenderer.removeBootstrapBackup();
|
|
97
97
|
|
|
98
98
|
await prerenderer.close();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFile, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { REMIXER_BUILD_DIR } from "./vars.mjs";
|
|
4
|
+
|
|
5
|
+
export async function injectBundleWrapper() {
|
|
6
|
+
const assetsDir = join(REMIXER_BUILD_DIR, "assets");
|
|
7
|
+
const indexPath = join(REMIXER_BUILD_DIR, "index.html");
|
|
8
|
+
const files = await readdir(assetsDir);
|
|
9
|
+
|
|
10
|
+
const bundleName = files.find((asset) => asset.endsWith(".js"));
|
|
11
|
+
const hash = bundleName.match(/-(.*?)\.js$/)?.[1];
|
|
12
|
+
|
|
13
|
+
const hashedBundleName = `bundle-wrapper-${hash}.js`;
|
|
14
|
+
|
|
15
|
+
const bundlePath = `/assets/${bundleName}`;
|
|
16
|
+
|
|
17
|
+
const rawBundleWrapper = await readFile(
|
|
18
|
+
new URL("./bundle-wrapper.js", import.meta.url),
|
|
19
|
+
"utf8",
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const rawIndexHtml = await readFile(
|
|
23
|
+
new URL(indexPath, import.meta.url),
|
|
24
|
+
"utf8",
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const parsedIndexHtml = rawIndexHtml
|
|
28
|
+
.split("\n")
|
|
29
|
+
.map((line) => {
|
|
30
|
+
if (line.includes(bundlePath)) {
|
|
31
|
+
const replaced = line.replace(
|
|
32
|
+
bundlePath,
|
|
33
|
+
`/assets/${hashedBundleName}`,
|
|
34
|
+
);
|
|
35
|
+
return replaced;
|
|
36
|
+
}
|
|
37
|
+
return line;
|
|
38
|
+
})
|
|
39
|
+
.join("\n");
|
|
40
|
+
|
|
41
|
+
const parsedBundleWrapper = rawBundleWrapper.replace(
|
|
42
|
+
"%BUNDLE_PATH%",
|
|
43
|
+
bundlePath,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
await writeFile(indexPath, parsedIndexHtml, "utf8");
|
|
47
|
+
await writeFile(
|
|
48
|
+
join(assetsDir, hashedBundleName),
|
|
49
|
+
parsedBundleWrapper,
|
|
50
|
+
"utf8",
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
"vite.config.ts": "vite.config.ts",
|
|
9
9
|
"robots.txt": "public/robots.txt",
|
|
10
10
|
".htaccess": "public/.htaccess",
|
|
11
|
-
"components/seo/SEOHead.tsx": "components/seo/SEOHead.tsx",
|
|
12
11
|
"remixer.ts": "lib/remixer.ts",
|
|
13
12
|
"remixer/actions.ts": "lib/remixer/actions.ts",
|
|
14
13
|
"remixer/anonToken.ts": "lib/remixer/anonToken.ts",
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Helmet } from "react-helmet-async";
|
|
2
|
-
import { useLanguage } from "@/context/LanguageContext";
|
|
3
|
-
import images from "@/assets/images.json";
|
|
4
|
-
|
|
5
|
-
interface SEOHeadProps {
|
|
6
|
-
titleKey?: string;
|
|
7
|
-
descriptionKey?: string;
|
|
8
|
-
ogImage?: string;
|
|
9
|
-
ogImageKey?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Canonical <head> for every page. Render exactly one <SEOHead /> per page
|
|
13
|
-
// inside pages/*.tsx; no raw <Helmet> anywhere else. Pulls og:image from
|
|
14
|
-
// assets/images.json by default so social sharing works without extra wiring.
|
|
15
|
-
export function SEOHead({
|
|
16
|
-
titleKey = "home.title",
|
|
17
|
-
descriptionKey = "home.description",
|
|
18
|
-
ogImage,
|
|
19
|
-
ogImageKey = "og_image",
|
|
20
|
-
}: SEOHeadProps) {
|
|
21
|
-
const { t } = useLanguage();
|
|
22
|
-
const siteTitle = import.meta.env.VITE_METADATA_TITLE as string | undefined;
|
|
23
|
-
const translated = t(titleKey);
|
|
24
|
-
const title = siteTitle ? `${translated} | ${siteTitle}` : translated;
|
|
25
|
-
const description = t(descriptionKey);
|
|
26
|
-
const resolvedOg =
|
|
27
|
-
ogImage ?? (images as Record<string, string>)[ogImageKey];
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Helmet>
|
|
31
|
-
<title>{title}</title>
|
|
32
|
-
<meta name="description" content={description} />
|
|
33
|
-
<meta property="og:title" content={title} />
|
|
34
|
-
<meta property="og:description" content={description} />
|
|
35
|
-
<meta property="og:type" content="website" />
|
|
36
|
-
{resolvedOg ? <meta property="og:image" content={resolvedOg} /> : null}
|
|
37
|
-
<meta name="twitter:card" content="summary_large_image" />
|
|
38
|
-
{resolvedOg ? <meta name="twitter:image" content={resolvedOg} /> : null}
|
|
39
|
-
</Helmet>
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default SEOHead;
|