wuppycms 0.0.0-stage → 0.2.0
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/dist/admin-fo4l4lu2.mjs +59 -0
- package/dist/astro.d.mts +20 -0
- package/dist/astro.mjs +302 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +210 -0
- package/dist/components-BrGAEPly.mjs +39 -0
- package/dist/config-CM8_-x_W.mjs +1242 -0
- package/dist/dist-D7fysV_5.mjs +9048 -0
- package/dist/frontmatter-DGaz9--t.mjs +24 -0
- package/dist/generate-iX4B_2U2.mjs +473 -0
- package/dist/i18n-CgLAHd9Q.mjs +79 -0
- package/dist/index-B6AHmgP9.d.mts +34 -0
- package/dist/index.d.mts +8636 -0
- package/dist/index.mjs +83 -0
- package/dist/live-runtime.d.mts +120 -0
- package/dist/live-runtime.mjs +207 -0
- package/dist/markdown.mjs +4 -0
- package/dist/mdx.d.mts +68 -0
- package/dist/mdx.mjs +4 -0
- package/dist/media-DGfJXgBA.mjs +356 -0
- package/dist/page-cache-middleware.d.mts +8 -0
- package/dist/page-cache-middleware.mjs +101 -0
- package/dist/publishing.d.mts +17 -0
- package/dist/publishing.mjs +42 -0
- package/dist/read-Bh4-a3Ap.mjs +18 -0
- package/dist/redirect-middleware.d.mts +6 -0
- package/dist/redirect-middleware.mjs +37 -0
- package/dist/render-DzH7Wil3.mjs +116 -0
- package/dist/routes/admin.d.mts +7 -0
- package/dist/routes/admin.mjs +10 -0
- package/dist/routes/api.d.mts +7 -0
- package/dist/routes/api.mjs +97 -0
- package/dist/routes/icons.d.mts +12 -0
- package/dist/routes/icons.mjs +36 -0
- package/dist/routes/robots.d.mts +7 -0
- package/dist/routes/robots.mjs +15 -0
- package/dist/routes/rss.d.mts +7 -0
- package/dist/routes/rss.mjs +20 -0
- package/dist/routes/sitemap.d.mts +7 -0
- package/dist/routes/sitemap.mjs +23 -0
- package/dist/routes/uploads.d.mts +7 -0
- package/dist/routes/uploads.mjs +11 -0
- package/dist/schemas-dHRJ1HeG.mjs +275 -0
- package/dist/seo.d.mts +125 -0
- package/dist/seo.mjs +130 -0
- package/dist/server-D92ryW2y.mjs +5883 -0
- package/dist/service-CgcvCG7l.mjs +353 -0
- package/dist/site-dF-xVPqe.mjs +148 -0
- package/dist/site.d.mts +28 -0
- package/dist/site.mjs +44 -0
- package/dist/sitemap-Ba0vil6a.mjs +46 -0
- package/dist/theme-pages-CRsBm1EX.mjs +246 -0
- package/dist/theme-seo-middleware.d.mts +7 -0
- package/dist/theme-seo-middleware.mjs +62 -0
- package/dist/visual-middleware.d.mts +7 -0
- package/dist/visual-middleware.mjs +71 -0
- package/package.json +72 -3
- package/README.md +0 -3
package/dist/seo.d.mts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
//#region src/seo/index.d.ts
|
|
2
|
+
interface Site {
|
|
3
|
+
url: string;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
interface SeoInput {
|
|
7
|
+
site: Site;
|
|
8
|
+
path: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
image?: string;
|
|
12
|
+
noindex?: boolean;
|
|
13
|
+
/** locale -> path, for hreflang */
|
|
14
|
+
alternates?: Record<string, string>;
|
|
15
|
+
/** Overrides the canonical URL (absolute or site-relative). */
|
|
16
|
+
canonical?: string;
|
|
17
|
+
/** How the page title and site name combine; `{title}` and `{site}` are replaced. Default `{title} | {site}`. */
|
|
18
|
+
titleTemplate?: string;
|
|
19
|
+
}
|
|
20
|
+
type MetaTag = {
|
|
21
|
+
name: string;
|
|
22
|
+
content: string;
|
|
23
|
+
} | {
|
|
24
|
+
property: string;
|
|
25
|
+
content: string;
|
|
26
|
+
};
|
|
27
|
+
interface LinkTag {
|
|
28
|
+
rel: string;
|
|
29
|
+
href: string;
|
|
30
|
+
hreflang?: string;
|
|
31
|
+
}
|
|
32
|
+
interface Seo {
|
|
33
|
+
title: string;
|
|
34
|
+
meta: MetaTag[];
|
|
35
|
+
links: LinkTag[];
|
|
36
|
+
}
|
|
37
|
+
declare function buildSeo({
|
|
38
|
+
site,
|
|
39
|
+
path,
|
|
40
|
+
title,
|
|
41
|
+
description,
|
|
42
|
+
image,
|
|
43
|
+
noindex,
|
|
44
|
+
alternates,
|
|
45
|
+
canonical: canonicalOverride,
|
|
46
|
+
titleTemplate
|
|
47
|
+
}: SeoInput): Seo;
|
|
48
|
+
declare const esc: (s: string) => string;
|
|
49
|
+
/** HTML for non-Astro consumers; every value is escaped. */
|
|
50
|
+
declare function renderHead(seo: Seo): string;
|
|
51
|
+
interface SitemapUrl {
|
|
52
|
+
loc: string;
|
|
53
|
+
lastmod?: string;
|
|
54
|
+
/** 0.0 to 1.0; omitted means the protocol default (0.5). */
|
|
55
|
+
priority?: number;
|
|
56
|
+
}
|
|
57
|
+
declare function buildSitemap(urls: SitemapUrl[]): string;
|
|
58
|
+
declare const buildRobots: (siteUrl: string) => string;
|
|
59
|
+
interface FeedItem {
|
|
60
|
+
link: string;
|
|
61
|
+
title: string;
|
|
62
|
+
date: Date;
|
|
63
|
+
description?: string;
|
|
64
|
+
}
|
|
65
|
+
declare function buildRss(site: {
|
|
66
|
+
url: string;
|
|
67
|
+
name: string;
|
|
68
|
+
}, items: FeedItem[]): string;
|
|
69
|
+
/** JSON-LD for a blog post or article. */
|
|
70
|
+
declare function articleJsonLd(input: {
|
|
71
|
+
site: Site;
|
|
72
|
+
url: string;
|
|
73
|
+
title: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
image?: string;
|
|
76
|
+
datePublished?: string;
|
|
77
|
+
dateModified?: string;
|
|
78
|
+
author?: string;
|
|
79
|
+
}): {
|
|
80
|
+
publisher: {
|
|
81
|
+
"@type": string;
|
|
82
|
+
name: string;
|
|
83
|
+
};
|
|
84
|
+
author?: {
|
|
85
|
+
"@type": string;
|
|
86
|
+
name: string;
|
|
87
|
+
} | undefined;
|
|
88
|
+
dateModified?: string | undefined;
|
|
89
|
+
datePublished?: string | undefined;
|
|
90
|
+
image?: string | undefined;
|
|
91
|
+
description?: string | undefined;
|
|
92
|
+
"@context": string;
|
|
93
|
+
"@type": string;
|
|
94
|
+
headline: string;
|
|
95
|
+
mainEntityOfPage: string;
|
|
96
|
+
};
|
|
97
|
+
/** JSON-LD for the site root; `searchPath` (e.g. `/search?q={q}`) enables the sitelinks search box. */
|
|
98
|
+
declare function websiteJsonLd(site: Site, searchPath?: string): {
|
|
99
|
+
potentialAction?: {
|
|
100
|
+
"@type": string;
|
|
101
|
+
target: string;
|
|
102
|
+
"query-input": string;
|
|
103
|
+
} | undefined;
|
|
104
|
+
"@context": string;
|
|
105
|
+
"@type": string;
|
|
106
|
+
name: string;
|
|
107
|
+
url: string;
|
|
108
|
+
};
|
|
109
|
+
declare function breadcrumbJsonLd(site: Site, trail: Array<{
|
|
110
|
+
name: string;
|
|
111
|
+
path: string;
|
|
112
|
+
}>): {
|
|
113
|
+
"@context": string;
|
|
114
|
+
"@type": string;
|
|
115
|
+
itemListElement: {
|
|
116
|
+
"@type": string;
|
|
117
|
+
position: number;
|
|
118
|
+
name: string;
|
|
119
|
+
item: string;
|
|
120
|
+
}[];
|
|
121
|
+
};
|
|
122
|
+
/** A `<script type="application/ld+json">` tag; `<` is escaped so values can never close the script early. */
|
|
123
|
+
declare const renderJsonLd: (data: object) => string;
|
|
124
|
+
//#endregion
|
|
125
|
+
export { FeedItem, LinkTag, MetaTag, Seo, SeoInput, Site, SitemapUrl, articleJsonLd, breadcrumbJsonLd, buildRobots, buildRss, buildSeo, buildSitemap, esc, renderHead, renderJsonLd, websiteJsonLd };
|
package/dist/seo.mjs
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
//#region src/seo/index.ts
|
|
2
|
+
const abs = (site, pathOrUrl) => new URL(pathOrUrl, site.url).href;
|
|
3
|
+
function buildSeo({ site, path, title, description, image, noindex, alternates, canonical: canonicalOverride, titleTemplate = "{title} | {site}" }) {
|
|
4
|
+
const url = new URL(path, site.url);
|
|
5
|
+
const canonical = canonicalOverride ? abs(site, canonicalOverride) : `${url.origin}${url.pathname}`;
|
|
6
|
+
return {
|
|
7
|
+
title: title ? titleTemplate.replace("{title}", () => title).replace("{site}", () => site.name) : site.name,
|
|
8
|
+
meta: [
|
|
9
|
+
...description ? [{
|
|
10
|
+
name: "description",
|
|
11
|
+
content: description
|
|
12
|
+
}] : [],
|
|
13
|
+
...noindex ? [{
|
|
14
|
+
name: "robots",
|
|
15
|
+
content: "noindex, nofollow"
|
|
16
|
+
}] : [],
|
|
17
|
+
{
|
|
18
|
+
property: "og:title",
|
|
19
|
+
content: title ?? site.name
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
property: "og:site_name",
|
|
23
|
+
content: site.name
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
property: "og:url",
|
|
27
|
+
content: canonical
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
property: "og:type",
|
|
31
|
+
content: "website"
|
|
32
|
+
},
|
|
33
|
+
...description ? [{
|
|
34
|
+
property: "og:description",
|
|
35
|
+
content: description
|
|
36
|
+
}] : [],
|
|
37
|
+
...image ? [{
|
|
38
|
+
property: "og:image",
|
|
39
|
+
content: abs(site, image)
|
|
40
|
+
}] : [],
|
|
41
|
+
{
|
|
42
|
+
name: "twitter:card",
|
|
43
|
+
content: image ? "summary_large_image" : "summary"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
links: [{
|
|
47
|
+
rel: "canonical",
|
|
48
|
+
href: canonical
|
|
49
|
+
}, ...Object.entries(alternates ?? {}).map(([hreflang, p]) => ({
|
|
50
|
+
rel: "alternate",
|
|
51
|
+
hreflang,
|
|
52
|
+
href: abs(site, p)
|
|
53
|
+
}))]
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
57
|
+
/** HTML for non-Astro consumers; every value is escaped. */
|
|
58
|
+
function renderHead(seo) {
|
|
59
|
+
const meta = seo.meta.map((m) => {
|
|
60
|
+
const [key, attr] = "name" in m ? ["name", m.name] : ["property", m.property];
|
|
61
|
+
return `<meta ${key}="${esc(attr)}" content="${esc(m.content)}">`;
|
|
62
|
+
});
|
|
63
|
+
const links = seo.links.map((l) => `<link rel="${esc(l.rel)}"${l.hreflang ? ` hreflang="${esc(l.hreflang)}"` : ""} href="${esc(l.href)}">`);
|
|
64
|
+
return [
|
|
65
|
+
`<title>${esc(seo.title)}</title>`,
|
|
66
|
+
...meta,
|
|
67
|
+
...links
|
|
68
|
+
].join("\n");
|
|
69
|
+
}
|
|
70
|
+
function buildSitemap(urls) {
|
|
71
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${urls.map((u) => `<url><loc>${esc(u.loc)}</loc>${u.lastmod ? `<lastmod>${esc(u.lastmod)}</lastmod>` : ""}${u.priority === void 0 ? "" : `<priority>${u.priority.toFixed(1)}</priority>`}</url>`).join("")}</urlset>\n`;
|
|
72
|
+
}
|
|
73
|
+
const buildRobots = (siteUrl) => `User-agent: *\nDisallow: /admin\nDisallow: /api\n\nSitemap: ${new URL("/sitemap.xml", siteUrl).href}\n`;
|
|
74
|
+
function buildRss(site, items) {
|
|
75
|
+
const rows = items.map((i) => `<item><title>${esc(i.title)}</title><link>${esc(i.link)}</link><guid>${esc(i.link)}</guid><pubDate>${i.date.toUTCString()}</pubDate>${i.description ? `<description>${esc(i.description)}</description>` : ""}</item>`);
|
|
76
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0"><channel><title>${esc(site.name)}</title><link>${esc(site.url)}</link><description>${esc(site.name)}</description>${rows.join("")}</channel></rss>\n`;
|
|
77
|
+
}
|
|
78
|
+
/** JSON-LD for a blog post or article. */
|
|
79
|
+
function articleJsonLd(input) {
|
|
80
|
+
const { site, url, title, description, image, datePublished, dateModified, author } = input;
|
|
81
|
+
return {
|
|
82
|
+
"@context": "https://schema.org",
|
|
83
|
+
"@type": "Article",
|
|
84
|
+
headline: title,
|
|
85
|
+
mainEntityOfPage: abs(site, url),
|
|
86
|
+
...description ? { description } : {},
|
|
87
|
+
...image ? { image: abs(site, image) } : {},
|
|
88
|
+
...datePublished ? { datePublished } : {},
|
|
89
|
+
...dateModified ? { dateModified } : {},
|
|
90
|
+
...author ? { author: {
|
|
91
|
+
"@type": "Person",
|
|
92
|
+
name: author
|
|
93
|
+
} } : {},
|
|
94
|
+
publisher: {
|
|
95
|
+
"@type": "Organization",
|
|
96
|
+
name: site.name
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** JSON-LD for the site root; `searchPath` (e.g. `/search?q={q}`) enables the sitelinks search box. */
|
|
101
|
+
function websiteJsonLd(site, searchPath) {
|
|
102
|
+
return {
|
|
103
|
+
"@context": "https://schema.org",
|
|
104
|
+
"@type": "WebSite",
|
|
105
|
+
name: site.name,
|
|
106
|
+
url: site.url,
|
|
107
|
+
...searchPath ? { potentialAction: {
|
|
108
|
+
"@type": "SearchAction",
|
|
109
|
+
target: abs(site, searchPath).replace(/%7Bq%7D|{q}/, "{search_term_string}"),
|
|
110
|
+
"query-input": "required name=search_term_string"
|
|
111
|
+
} } : {}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function breadcrumbJsonLd(site, trail) {
|
|
115
|
+
return {
|
|
116
|
+
"@context": "https://schema.org",
|
|
117
|
+
"@type": "BreadcrumbList",
|
|
118
|
+
itemListElement: trail.map((t, i) => ({
|
|
119
|
+
"@type": "ListItem",
|
|
120
|
+
position: i + 1,
|
|
121
|
+
name: t.name,
|
|
122
|
+
item: abs(site, t.path)
|
|
123
|
+
}))
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** A `<script type="application/ld+json">` tag; `<` is escaped so values can never close the script early. */
|
|
127
|
+
const renderJsonLd = (data) => `<script type="application/ld+json">${JSON.stringify(data).replaceAll("<", "\\u003c")}<\/script>`;
|
|
128
|
+
|
|
129
|
+
//#endregion
|
|
130
|
+
export { articleJsonLd, breadcrumbJsonLd, buildRobots, buildRss, buildSeo, buildSitemap, esc, renderHead, renderJsonLd, websiteJsonLd };
|