Compare commits
No commits in common. "df2d18d3d94d7e3b3cbd90573b269a42938ca8f8" and "2def582b005ee0f4ea68f2c1a59f3b76cc7f812a" have entirely different histories.
df2d18d3d9
...
2def582b00
@ -1,3 +0,0 @@
|
|||||||
import { sitemap } from "./services/Sitemap";
|
|
||||||
|
|
||||||
sitemap.generateSitemap();
|
|
||||||
@ -4,9 +4,7 @@ export function buildPublicUrl(pageContext: PageContext, resource: string) {
|
|||||||
const { baseUrl } = pageContext;
|
const { baseUrl } = pageContext;
|
||||||
const url = new URL(
|
const url = new URL(
|
||||||
resource,
|
resource,
|
||||||
process.env.NODE_ENV === "production"
|
process.env.NODE_ENV === "production" ? "https://memento-dev.fr" : baseUrl,
|
||||||
? "https://memento-dev.fr"
|
|
||||||
: baseUrl || "http://localhost:5500",
|
|
||||||
).toString();
|
).toString();
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
{
|
{
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun ./fastify-entry.ts",
|
"dev": "bun ./fastify-entry.ts",
|
||||||
"build": "bun run build:sitemap && bun run build:server",
|
"build": "cross-env DEBUG=vike:error,vike:log vike build",
|
||||||
"build:server": "cross-env DEBUG=vike:error,vike:log vike build",
|
|
||||||
"build:sitemap": "cross-env NODE_ENV=production bun ./build-sitemap.ts",
|
|
||||||
"preview": "cross-env NODE_ENV=production bun ./fastify-server.ts",
|
"preview": "cross-env NODE_ENV=production bun ./fastify-server.ts",
|
||||||
"production": "bun run build && bun run preview",
|
"production": "bun run build && bun run preview",
|
||||||
"lint": "biome lint --write .",
|
"lint": "biome lint --write .",
|
||||||
|
|||||||
@ -1,23 +1,13 @@
|
|||||||
import { usePageContext } from "vike-solid/usePageContext";
|
|
||||||
import blurCyanImage from "@/images/blur-cyan.webp";
|
import blurCyanImage from "@/images/blur-cyan.webp";
|
||||||
import { buildPublicUrl } from "@/buildPublicUrl";
|
|
||||||
import logoUrl from "@/assets/logo.svg";
|
import logoUrl from "@/assets/logo.svg";
|
||||||
|
|
||||||
// https://vike.dev/Head
|
// https://vike.dev/Head
|
||||||
|
|
||||||
export default function HeadDefault() {
|
export default function HeadDefault() {
|
||||||
const pageContext = usePageContext();
|
|
||||||
|
|
||||||
const getCanonicalUrl = () => {
|
|
||||||
return buildPublicUrl(pageContext, pageContext.urlParsed.pathname);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<link rel="icon" href={logoUrl} />
|
<link rel="icon" href={logoUrl} />
|
||||||
|
|
||||||
<link rel="canonical" href={getCanonicalUrl()} />
|
|
||||||
|
|
||||||
<script
|
<script
|
||||||
defer
|
defer
|
||||||
src="https://cloud.umami.is/script.js"
|
src="https://cloud.umami.is/script.js"
|
||||||
|
|||||||
@ -1,38 +1,8 @@
|
|||||||
import type { OnPageTransitionEndAsync, PageContext } from "vike/types";
|
import type { OnPageTransitionEndAsync } from "vike/types";
|
||||||
|
|
||||||
import { buildPublicUrl } from "@/buildPublicUrl";
|
|
||||||
import NProgress from "nprogress";
|
import NProgress from "nprogress";
|
||||||
|
|
||||||
export const onPageTransitionEnd: OnPageTransitionEndAsync = async (
|
export const onPageTransitionEnd: OnPageTransitionEndAsync = async () => {
|
||||||
pageContext,
|
|
||||||
) => {
|
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
NProgress.remove();
|
NProgress.remove();
|
||||||
|
|
||||||
updateCanonicalTag(pageContext);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateCanonicalTag = (pageContext: PageContext) => {
|
|
||||||
const canonicalTag = findOrCreateCanonicalTag();
|
|
||||||
const canonicalUrl = buildPublicUrl(
|
|
||||||
pageContext,
|
|
||||||
pageContext.urlParsed.pathname,
|
|
||||||
);
|
|
||||||
|
|
||||||
canonicalTag.href = canonicalUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
const findOrCreateCanonicalTag = () => {
|
|
||||||
const head = document.head;
|
|
||||||
let canonicalTag: HTMLLinkElement | null = head.querySelector(
|
|
||||||
"link[rel=canonical]",
|
|
||||||
);
|
|
||||||
if (canonicalTag) return canonicalTag;
|
|
||||||
|
|
||||||
canonicalTag = document.createElement("link");
|
|
||||||
canonicalTag.rel = "canonical";
|
|
||||||
|
|
||||||
document.head.appendChild(canonicalTag);
|
|
||||||
|
|
||||||
return canonicalTag;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
User-agent: *
|
|
||||||
Disallow:
|
|
||||||
Sitemap: https://memento-dev.fr/sitemap.xml
|
|
||||||
@ -1,167 +0,0 @@
|
|||||||
import { navigation } from "@/libs/navigation";
|
|
||||||
import path from "node:path";
|
|
||||||
import fs from "node:fs";
|
|
||||||
|
|
||||||
const __dirname = path.resolve();
|
|
||||||
|
|
||||||
const getBaseUrl = () => {
|
|
||||||
if (process.env.NODE_ENV === "production") {
|
|
||||||
return "https://memento-dev.fr";
|
|
||||||
}
|
|
||||||
|
|
||||||
return `http://localhost:${process.env.PORT || 3000}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
type SitemapElement = {
|
|
||||||
location: string;
|
|
||||||
lastmod: string;
|
|
||||||
priority: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Sitemap {
|
|
||||||
private readonly pagesPath = path.join(__dirname, "pages");
|
|
||||||
private readonly sitemapPath = path.join(__dirname, "public", "sitemap.xml");
|
|
||||||
private readonly lastModified = new Date().toISOString();
|
|
||||||
private readonly baseUrl = getBaseUrl();
|
|
||||||
|
|
||||||
private urls: SitemapElement[] = [];
|
|
||||||
private sitemap = "";
|
|
||||||
|
|
||||||
private static instance: Sitemap;
|
|
||||||
|
|
||||||
private constructor() {}
|
|
||||||
|
|
||||||
public static getInstance(): Sitemap {
|
|
||||||
if (!Sitemap.instance) {
|
|
||||||
Sitemap.instance = new Sitemap();
|
|
||||||
}
|
|
||||||
return Sitemap.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private resetMemory(): void {
|
|
||||||
this.sitemap = "";
|
|
||||||
this.urls = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
private prependSitemap(): void {
|
|
||||||
this.sitemap = `<?xml version="1.0" encoding="UTF-8"?>`;
|
|
||||||
this.sitemap += `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private appendSitemap(): void {
|
|
||||||
this.sitemap += "</urlset>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private addSitemapElement(url: SitemapElement): void {
|
|
||||||
this.sitemap += "<url>";
|
|
||||||
this.sitemap += `<loc>${url.location}</loc>`;
|
|
||||||
this.sitemap += `<lastmod>${url.lastmod || this.lastModified}</lastmod>`;
|
|
||||||
this.sitemap += `<priority>${url.priority}</priority>`;
|
|
||||||
this.sitemap += "</url>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildSitemap(): void {
|
|
||||||
this.prependSitemap();
|
|
||||||
this.urls.forEach(this.addSitemapElement.bind(this));
|
|
||||||
this.appendSitemap();
|
|
||||||
}
|
|
||||||
|
|
||||||
private saveSitemap(): void {
|
|
||||||
fs.writeFileSync(this.sitemapPath, this.sitemap, "utf8");
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadPriority(href: string): string {
|
|
||||||
const isRootUrl = ["/", ""].includes(href);
|
|
||||||
|
|
||||||
if (isRootUrl) return "1.0";
|
|
||||||
const countOfSlashes = (href.match(/\//g) || []).length;
|
|
||||||
return (1 - countOfSlashes * 0.1).toFixed(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadLastModified(stat?: fs.Stats): string {
|
|
||||||
return stat ? stat.mtime.toISOString() : this.lastModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getFileServerLocation(href: string) {
|
|
||||||
if (href === "/") return path.join(this.pagesPath, "index", "+Page.mdx");
|
|
||||||
return path.join(this.pagesPath, href.replace("/", ""), "+Page.mdx");
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadSubitems(
|
|
||||||
subitems: (typeof navigation)[number]["links"][number]["subitems"],
|
|
||||||
): void {
|
|
||||||
for (const subitem of subitems) {
|
|
||||||
const fileLocation = this.getFileServerLocation(subitem.href);
|
|
||||||
let fileDetails: fs.Stats | undefined;
|
|
||||||
try {
|
|
||||||
fileDetails = fs.statSync(fileLocation);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error loading file for ${subitem.href}:`, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const priority = this.loadPriority(subitem.href);
|
|
||||||
const lastmod = this.loadLastModified(fileDetails);
|
|
||||||
const location = `${this.baseUrl}${subitem.href}`;
|
|
||||||
|
|
||||||
this.urls.push({
|
|
||||||
location,
|
|
||||||
lastmod,
|
|
||||||
priority,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadSection(section: (typeof navigation)[number]): void {
|
|
||||||
for (const link of section.links) {
|
|
||||||
if (link.subitems.length > 0) {
|
|
||||||
this.loadSubitems(link.subitems);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fileLocation = this.getFileServerLocation(link.href);
|
|
||||||
let fileDetails: fs.Stats | undefined;
|
|
||||||
|
|
||||||
try {
|
|
||||||
fileDetails = fs.statSync(fileLocation);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error loading file for ${link.href}:`, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const priority = this.loadPriority(link.href);
|
|
||||||
const lastmod = this.loadLastModified(fileDetails);
|
|
||||||
const location = `${this.baseUrl}${link.href}`;
|
|
||||||
|
|
||||||
this.urls.push({
|
|
||||||
location,
|
|
||||||
lastmod,
|
|
||||||
priority,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadUrls(): void {
|
|
||||||
navigation.forEach(this.loadSection.bind(this));
|
|
||||||
|
|
||||||
this.urls = Array.from(new Set(this.urls)).sort((a, b) => {
|
|
||||||
return a.location.localeCompare(b.location);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSitemap(): string {
|
|
||||||
if (!this.sitemap) this.generateSitemap();
|
|
||||||
return this.sitemap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public generateSitemap(): void {
|
|
||||||
console.log("Generating sitemap...");
|
|
||||||
|
|
||||||
this.resetMemory();
|
|
||||||
this.loadUrls();
|
|
||||||
this.buildSitemap();
|
|
||||||
this.saveSitemap();
|
|
||||||
|
|
||||||
console.log("Sitemap generated successfully.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const sitemap = Sitemap.getInstance();
|
|
||||||
Loading…
Reference in New Issue
Block a user