@zedtech/zedkit-seo 0.0.0 → 0.1.1
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/README.md +16 -3
- package/dist/description.d.ts +17 -0
- package/dist/description.d.ts.map +1 -0
- package/dist/description.js +36 -0
- package/dist/description.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonld.d.ts +31 -0
- package/dist/jsonld.d.ts.map +1 -0
- package/dist/jsonld.js +49 -0
- package/dist/jsonld.js.map +1 -0
- package/dist/llms.d.ts +17 -0
- package/dist/llms.d.ts.map +1 -0
- package/dist/llms.js +30 -0
- package/dist/llms.js.map +1 -0
- package/dist/metadata.d.ts +85 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +65 -0
- package/dist/metadata.js.map +1 -0
- package/dist/robots.d.ts +25 -0
- package/dist/robots.d.ts.map +1 -0
- package/dist/robots.js +14 -0
- package/dist/robots.js.map +1 -0
- package/dist/sitemap.d.ts +24 -0
- package/dist/sitemap.d.ts.map +1 -0
- package/dist/sitemap.js +16 -0
- package/dist/sitemap.js.map +1 -0
- package/dist/slug.d.ts +5 -0
- package/dist/slug.d.ts.map +1 -0
- package/dist/slug.js +22 -0
- package/dist/slug.js.map +1 -0
- package/dist/video-sitemap.d.ts +22 -0
- package/dist/video-sitemap.d.ts.map +1 -0
- package/dist/video-sitemap.js +31 -0
- package/dist/video-sitemap.js.map +1 -0
- package/package.json +20 -2
package/README.md
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
# @zedtech/zedkit-seo
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@zedtech/zedkit-seo)
|
|
4
|
+
[](https://github.com/zedtech-fr/zedkit/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
Ship sitemaps, robots, typed JSON-LD, metadata, hreflang, slugs and
|
|
7
|
+
llms.txt without thinking about the specs. Pure functions,
|
|
8
|
+
options-driven, no brand, no CMS. Original work by the same author.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
6
11
|
|
|
7
12
|
```sh
|
|
8
13
|
pnpm add @zedtech/zedkit-seo
|
|
9
14
|
```
|
|
10
15
|
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
11
18
|
```ts
|
|
12
19
|
import { buildRobots, buildSitemapEntries } from "@zedtech/zedkit-seo";
|
|
13
20
|
|
|
@@ -19,6 +26,12 @@ export function robots() {
|
|
|
19
26
|
}
|
|
20
27
|
```
|
|
21
28
|
|
|
29
|
+
## When to use
|
|
30
|
+
|
|
31
|
+
Reach for this package when you render SEO outputs (robots, sitemaps,
|
|
32
|
+
metadata, JSON-LD) from plain data. It never talks to a CMS: pair it
|
|
33
|
+
with `@zedtech/zedkit-payload-seo` when your content lives in Payload.
|
|
34
|
+
|
|
22
35
|
Return shapes follow the Next.js Metadata API (`MetadataRoute.Robots`,
|
|
23
36
|
`MetadataRoute.Sitemap`, `Metadata`) so builders drop straight into
|
|
24
37
|
`robots.ts`, `sitemap.ts`, and `generateMetadata`. JSON-LD builders
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const SEO_DESCRIPTION_MAX = 160;
|
|
2
|
+
/** Collapse whitespace and cap at 160 chars with an ellipsis (SERP length). */
|
|
3
|
+
export declare function truncateDescription(text: string, max?: number): string;
|
|
4
|
+
export type LocalizedField = string | Partial<Record<string, string>> | null | undefined;
|
|
5
|
+
/** Resolve a localized CMS value: exact locale, then fallbacks, then first. */
|
|
6
|
+
export declare function resolveLocalizedField(value: LocalizedField, locale: string, fallbackLocales?: string[]): string;
|
|
7
|
+
export interface DescriptionSource {
|
|
8
|
+
/** Explicit SEO description (wins when present). */
|
|
9
|
+
custom?: string | null;
|
|
10
|
+
/** Plain-text body to derive from (convert rich text to text first). */
|
|
11
|
+
bodyText?: string | null;
|
|
12
|
+
/** Localized title, last resort. */
|
|
13
|
+
title?: LocalizedField;
|
|
14
|
+
}
|
|
15
|
+
/** Description fallback chain: custom → body text → title, truncated. */
|
|
16
|
+
export declare function resolveDescription(source: DescriptionSource, locale?: string): string;
|
|
17
|
+
//# sourceMappingURL=description.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"description.d.ts","sourceRoot":"","sources":["../src/description.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAA4B,GAAG,MAAM,CAI3F;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AAEzF,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,EACd,eAAe,GAAE,MAAM,EAAW,GACjC,MAAM,CAWR;AAED,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oCAAoC;IACpC,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,SAAO,GAAG,MAAM,CAMnF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const SEO_DESCRIPTION_MAX = 160;
|
|
2
|
+
/** Collapse whitespace and cap at 160 chars with an ellipsis (SERP length). */
|
|
3
|
+
export function truncateDescription(text, max = SEO_DESCRIPTION_MAX) {
|
|
4
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
5
|
+
if (normalized.length <= max)
|
|
6
|
+
return normalized;
|
|
7
|
+
return `${normalized.slice(0, max - 1).trimEnd()}…`;
|
|
8
|
+
}
|
|
9
|
+
/** Resolve a localized CMS value: exact locale, then fallbacks, then first. */
|
|
10
|
+
export function resolveLocalizedField(value, locale, fallbackLocales = ["en"]) {
|
|
11
|
+
if (typeof value === "string")
|
|
12
|
+
return value.trim();
|
|
13
|
+
if (value === null || value === undefined)
|
|
14
|
+
return "";
|
|
15
|
+
for (const candidate of [locale, ...fallbackLocales]) {
|
|
16
|
+
const hit = value[candidate];
|
|
17
|
+
if (hit !== undefined && hit.trim().length > 0)
|
|
18
|
+
return hit.trim();
|
|
19
|
+
}
|
|
20
|
+
for (const hit of Object.values(value)) {
|
|
21
|
+
if (hit !== undefined && hit.trim().length > 0)
|
|
22
|
+
return hit.trim();
|
|
23
|
+
}
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
/** Description fallback chain: custom → body text → title, truncated. */
|
|
27
|
+
export function resolveDescription(source, locale = "en") {
|
|
28
|
+
const custom = (source.custom ?? "").trim();
|
|
29
|
+
if (custom.length > 0)
|
|
30
|
+
return truncateDescription(custom);
|
|
31
|
+
const body = (source.bodyText ?? "").trim();
|
|
32
|
+
if (body.length > 0)
|
|
33
|
+
return truncateDescription(body);
|
|
34
|
+
return truncateDescription(resolveLocalizedField(source.title, locale));
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=description.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"description.js","sourceRoot":"","sources":["../src/description.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,MAAc,mBAAmB;IACjF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAI,UAAU,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,UAAU,CAAC;IAChD,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC;AACtD,CAAC;AAID,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB,CACnC,KAAqB,EACrB,MAAc,EACd,kBAA4B,CAAC,IAAI,CAAC;IAElC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;IACnD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrD,KAAK,MAAM,SAAS,IAAI,CAAC,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpE,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAWD,yEAAyE;AACzE,MAAM,UAAU,kBAAkB,CAAC,MAAyB,EAAE,MAAM,GAAG,IAAI;IACzE,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,mBAAmB,CAAC,qBAAqB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAC1E,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { SEO_DESCRIPTION_MAX, resolveDescription, resolveLocalizedField, truncateDescription, type DescriptionSource, type LocalizedField, } from "./description.js";
|
|
2
|
+
export { buildArticleJsonLd, buildBreadcrumbJsonLd, buildOrganizationJsonLd, buildWebPageJsonLd, type ArticleJsonLdOptions, type BreadcrumbItem, type OrganizationJsonLdOptions, type WebPageJsonLdOptions, } from "./jsonld.js";
|
|
3
|
+
export { buildLlmsFull, llmsTextResponse, normalizeLlmsBody, type LlmsFullSection, type LlmsTextResponseOptions, } from "./llms.js";
|
|
4
|
+
export { buildPageMetadata, type BuildPageMetadataOptions, type OpenGraphImage, type PageContent, type PageMetadata, type SiteMetadata, } from "./metadata.js";
|
|
5
|
+
export { buildRobots, type BuildRobotsOptions, type RobotsConfig } from "./robots.js";
|
|
6
|
+
export { buildSitemapEntries, type BuildSitemapOptions, type SitemapEntry, type SitemapPage, } from "./sitemap.js";
|
|
7
|
+
export { isDraftSlug, normalizeSlug } from "./slug.js";
|
|
8
|
+
export { buildVideoSitemap, escapeXml, type BuildVideoSitemapOptions, type VideoSitemapEntry, } from "./video-sitemap.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,uBAAuB,GAC7B,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EACL,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,GACvB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { SEO_DESCRIPTION_MAX, resolveDescription, resolveLocalizedField, truncateDescription, } from "./description.js";
|
|
2
|
+
export { buildArticleJsonLd, buildBreadcrumbJsonLd, buildOrganizationJsonLd, buildWebPageJsonLd, } from "./jsonld.js";
|
|
3
|
+
export { buildLlmsFull, llmsTextResponse, normalizeLlmsBody, } from "./llms.js";
|
|
4
|
+
export { buildPageMetadata, } from "./metadata.js";
|
|
5
|
+
export { buildRobots } from "./robots.js";
|
|
6
|
+
export { buildSitemapEntries, } from "./sitemap.js";
|
|
7
|
+
export { isDraftSlug, normalizeSlug } from "./slug.js";
|
|
8
|
+
export { buildVideoSitemap, escapeXml, } from "./video-sitemap.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GAGpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,GAKnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAGlB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,GAMlB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAA8C,MAAM,aAAa,CAAC;AACtF,OAAO,EACL,mBAAmB,GAIpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,iBAAiB,EACjB,SAAS,GAGV,MAAM,oBAAoB,CAAC"}
|
package/dist/jsonld.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Article, BreadcrumbList, Organization, WebPage, WithContext } from "schema-dts";
|
|
2
|
+
export interface OrganizationJsonLdOptions {
|
|
3
|
+
name: string;
|
|
4
|
+
url: string;
|
|
5
|
+
logoUrl?: string;
|
|
6
|
+
sameAs?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function buildOrganizationJsonLd(options: OrganizationJsonLdOptions): WithContext<Organization>;
|
|
9
|
+
export interface WebPageJsonLdOptions {
|
|
10
|
+
title: string;
|
|
11
|
+
description: string;
|
|
12
|
+
url: string;
|
|
13
|
+
breadcrumb?: BreadcrumbList;
|
|
14
|
+
}
|
|
15
|
+
export declare function buildWebPageJsonLd(options: WebPageJsonLdOptions): WithContext<WebPage>;
|
|
16
|
+
export interface BreadcrumbItem {
|
|
17
|
+
name: string;
|
|
18
|
+
url: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function buildBreadcrumbJsonLd(items: BreadcrumbItem[]): WithContext<BreadcrumbList>;
|
|
21
|
+
export interface ArticleJsonLdOptions {
|
|
22
|
+
title: string;
|
|
23
|
+
description: string;
|
|
24
|
+
url: string;
|
|
25
|
+
datePublished: string;
|
|
26
|
+
dateModified?: string;
|
|
27
|
+
authorName?: string;
|
|
28
|
+
imageUrl?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function buildArticleJsonLd(options: ArticleJsonLdOptions): WithContext<Article>;
|
|
31
|
+
//# sourceMappingURL=jsonld.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonld.d.ts","sourceRoot":"","sources":["../src/jsonld.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,YAAY,EACZ,OAAO,EACP,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,yBAAyB,GAAG,WAAW,CAAC,YAAY,CAAC,CAUrG;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,CAAC,OAAO,CAAC,CAStF;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC,cAAc,CAAC,CAW1F;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,CAAC,OAAO,CAAC,CActF"}
|
package/dist/jsonld.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function buildOrganizationJsonLd(options) {
|
|
2
|
+
return {
|
|
3
|
+
"@context": "https://schema.org",
|
|
4
|
+
"@type": "Organization",
|
|
5
|
+
"@id": `${options.url.replace(/\/$/, "")}/#organization`,
|
|
6
|
+
name: options.name,
|
|
7
|
+
url: options.url,
|
|
8
|
+
...(options.logoUrl === undefined ? {} : { logo: options.logoUrl }),
|
|
9
|
+
...(options.sameAs === undefined ? {} : { sameAs: options.sameAs }),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function buildWebPageJsonLd(options) {
|
|
13
|
+
return {
|
|
14
|
+
"@context": "https://schema.org",
|
|
15
|
+
"@type": "WebPage",
|
|
16
|
+
name: options.title,
|
|
17
|
+
description: options.description,
|
|
18
|
+
url: options.url,
|
|
19
|
+
...(options.breadcrumb === undefined ? {} : { breadcrumb: options.breadcrumb }),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function buildBreadcrumbJsonLd(items) {
|
|
23
|
+
return {
|
|
24
|
+
"@context": "https://schema.org",
|
|
25
|
+
"@type": "BreadcrumbList",
|
|
26
|
+
itemListElement: items.map((item, index) => ({
|
|
27
|
+
"@type": "ListItem",
|
|
28
|
+
position: index + 1,
|
|
29
|
+
name: item.name,
|
|
30
|
+
item: item.url,
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function buildArticleJsonLd(options) {
|
|
35
|
+
return {
|
|
36
|
+
"@context": "https://schema.org",
|
|
37
|
+
"@type": "Article",
|
|
38
|
+
headline: options.title,
|
|
39
|
+
description: options.description,
|
|
40
|
+
url: options.url,
|
|
41
|
+
datePublished: options.datePublished,
|
|
42
|
+
...(options.dateModified === undefined ? {} : { dateModified: options.dateModified }),
|
|
43
|
+
...(options.authorName === undefined
|
|
44
|
+
? {}
|
|
45
|
+
: { author: { "@type": "Person", name: options.authorName } }),
|
|
46
|
+
...(options.imageUrl === undefined ? {} : { image: options.imageUrl }),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=jsonld.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonld.js","sourceRoot":"","sources":["../src/jsonld.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,uBAAuB,CAAC,OAAkC;IACxE,OAAO;QACL,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,cAAc;QACvB,KAAK,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB;QACxD,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;QACnE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KACpE,CAAC;AACJ,CAAC;AASD,MAAM,UAAU,kBAAkB,CAAC,OAA6B;IAC9D,OAAO;QACL,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,OAAO,CAAC,KAAK;QACnB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;KAChF,CAAC;AACJ,CAAC;AAOD,MAAM,UAAU,qBAAqB,CAAC,KAAuB;IAC3D,OAAO;QACL,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,gBAAgB;QACzB,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YAC3C,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,KAAK,GAAG,CAAC;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,GAAG;SACf,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAYD,MAAM,UAAU,kBAAkB,CAAC,OAA6B;IAC9D,OAAO;QACL,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,SAAS;QAClB,QAAQ,EAAE,OAAO,CAAC,KAAK;QACvB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;QACrF,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS;YAClC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;KACvE,CAAC;AACJ,CAAC"}
|
package/dist/llms.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Normalize CMS-stored llms.txt content (CRLF + surrounding blank lines). */
|
|
2
|
+
export declare function normalizeLlmsBody(body: string): string;
|
|
3
|
+
export interface LlmsTextResponseOptions {
|
|
4
|
+
/** Normalized body; empty answers 404 (nothing published yet). */
|
|
5
|
+
body: string;
|
|
6
|
+
/** Cache for served bodies. Defaults to one minute. */
|
|
7
|
+
cacheControl?: string;
|
|
8
|
+
}
|
|
9
|
+
/** `text/plain` Response for an llms.txt route (200 with body, else 404). */
|
|
10
|
+
export declare function llmsTextResponse(options: LlmsTextResponseOptions): Response;
|
|
11
|
+
export interface LlmsFullSection {
|
|
12
|
+
title: string;
|
|
13
|
+
body: string;
|
|
14
|
+
}
|
|
15
|
+
/** Join titled sections into one llms-full document (skips empty bodies). */
|
|
16
|
+
export declare function buildLlmsFull(sections: LlmsFullSection[]): string;
|
|
17
|
+
//# sourceMappingURL=llms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms.d.ts","sourceRoot":"","sources":["../src/llms.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,QAAQ,CAe3E;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,CAMjE"}
|
package/dist/llms.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Normalize CMS-stored llms.txt content (CRLF + surrounding blank lines). */
|
|
2
|
+
export function normalizeLlmsBody(body) {
|
|
3
|
+
return body.replace(/\r\n/g, "\n").trim();
|
|
4
|
+
}
|
|
5
|
+
/** `text/plain` Response for an llms.txt route (200 with body, else 404). */
|
|
6
|
+
export function llmsTextResponse(options) {
|
|
7
|
+
const body = normalizeLlmsBody(options.body);
|
|
8
|
+
if (body.length === 0) {
|
|
9
|
+
return new Response("Not Found", {
|
|
10
|
+
status: 404,
|
|
11
|
+
headers: { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" },
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return new Response(`${body}\n`, {
|
|
15
|
+
status: 200,
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
18
|
+
"Cache-Control": options.cacheControl ?? "public, max-age=60",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** Join titled sections into one llms-full document (skips empty bodies). */
|
|
23
|
+
export function buildLlmsFull(sections) {
|
|
24
|
+
return sections
|
|
25
|
+
.map((section) => ({ title: section.title.trim(), body: normalizeLlmsBody(section.body) }))
|
|
26
|
+
.filter((section) => section.title.length > 0 && section.body.length > 0)
|
|
27
|
+
.map((section) => `# ${section.title}\n\n${section.body}`)
|
|
28
|
+
.join("\n\n");
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=llms.js.map
|
package/dist/llms.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms.js","sourceRoot":"","sources":["../src/llms.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5C,CAAC;AASD,6EAA6E;AAC7E,MAAM,UAAU,gBAAgB,CAAC,OAAgC;IAC/D,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE;YAC/B,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,EAAE,cAAc,EAAE,2BAA2B,EAAE,eAAe,EAAE,UAAU,EAAE;SACtF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,QAAQ,CAAC,GAAG,IAAI,IAAI,EAAE;QAC/B,MAAM,EAAE,GAAG;QACX,OAAO,EAAE;YACP,cAAc,EAAE,2BAA2B;YAC3C,eAAe,EAAE,OAAO,CAAC,YAAY,IAAI,oBAAoB;SAC9D;KACF,CAAC,CAAC;AACL,CAAC;AAOD,6EAA6E;AAC7E,MAAM,UAAU,aAAa,CAAC,QAA2B;IACvD,OAAO,QAAQ;SACZ,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SAC1F,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SACxE,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,KAAK,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;SACzD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page metadata, shaped for Next.js `Metadata` (generateMetadata return).
|
|
3
|
+
* Structural on purpose: no Next dependency, assignable where used.
|
|
4
|
+
*/
|
|
5
|
+
export interface PageMetadata {
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
keywords?: string[];
|
|
9
|
+
authors?: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
}>;
|
|
12
|
+
creator?: string;
|
|
13
|
+
publisher?: string;
|
|
14
|
+
metadataBase?: URL;
|
|
15
|
+
alternates?: {
|
|
16
|
+
canonical?: string;
|
|
17
|
+
languages?: Record<string, string>;
|
|
18
|
+
};
|
|
19
|
+
openGraph?: {
|
|
20
|
+
type: "website" | "article";
|
|
21
|
+
locale?: string;
|
|
22
|
+
url?: string;
|
|
23
|
+
siteName?: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
images?: Array<{
|
|
27
|
+
url: string;
|
|
28
|
+
width?: number;
|
|
29
|
+
height?: number;
|
|
30
|
+
alt?: string;
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
33
|
+
twitter?: {
|
|
34
|
+
card: "summary" | "summary_large_image";
|
|
35
|
+
title?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
images?: string[];
|
|
38
|
+
};
|
|
39
|
+
robots?: {
|
|
40
|
+
index: boolean;
|
|
41
|
+
follow: boolean;
|
|
42
|
+
googleBot?: {
|
|
43
|
+
index: boolean;
|
|
44
|
+
follow: boolean;
|
|
45
|
+
"max-video-preview"?: number;
|
|
46
|
+
"max-image-preview"?: "none" | "standard" | "large";
|
|
47
|
+
"max-snippet"?: number;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export interface SiteMetadata {
|
|
52
|
+
name: string;
|
|
53
|
+
url: string;
|
|
54
|
+
defaultLocale: string;
|
|
55
|
+
locales: string[];
|
|
56
|
+
}
|
|
57
|
+
export interface PageContent {
|
|
58
|
+
title: string;
|
|
59
|
+
description: string;
|
|
60
|
+
keywords?: string[];
|
|
61
|
+
}
|
|
62
|
+
export interface OpenGraphImage {
|
|
63
|
+
url: string;
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
}
|
|
67
|
+
export interface BuildPageMetadataOptions {
|
|
68
|
+
site: SiteMetadata;
|
|
69
|
+
page: PageContent;
|
|
70
|
+
/** Active locale, e.g. `"en"`. */
|
|
71
|
+
locale: string;
|
|
72
|
+
/** Full pathname including the locale prefix, e.g. `/en/work/slug`. */
|
|
73
|
+
pathname: string;
|
|
74
|
+
/** Brand or page social image. */
|
|
75
|
+
ogImage?: OpenGraphImage;
|
|
76
|
+
/** Open Graph locale tag, e.g. `"en_US"`. Defaults to `<locale>_<LOCALE>`. */
|
|
77
|
+
openGraphLocale?: string;
|
|
78
|
+
/** Page-level robots overrides (e.g. `{ index: false }` for drafts). */
|
|
79
|
+
robots?: {
|
|
80
|
+
index?: boolean;
|
|
81
|
+
follow?: boolean;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export declare function buildPageMetadata(options: BuildPageMetadataOptions): PageMetadata;
|
|
85
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC,CAAC;IACF,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;QAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAChF,CAAC;IACF,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,SAAS,GAAG,qBAAqB,CAAC;QACxC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,CAAC,EAAE;YACV,KAAK,EAAE,OAAO,CAAC;YACf,MAAM,EAAE,OAAO,CAAC;YAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;YAC7B,mBAAmB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;YACpD,aAAa,CAAC,EAAE,MAAM,CAAC;SACxB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;IAClB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAChD;AAWD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,YAAY,CAuDjF"}
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
function stripLocale(pathname, locales) {
|
|
2
|
+
for (const locale of locales) {
|
|
3
|
+
if (pathname === `/${locale}` || pathname.startsWith(`/${locale}/`)) {
|
|
4
|
+
return pathname.slice(locale.length + 1) || "/";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
return pathname || "/";
|
|
8
|
+
}
|
|
9
|
+
export function buildPageMetadata(options) {
|
|
10
|
+
const { site, page, locale } = options;
|
|
11
|
+
const barePath = stripLocale(options.pathname, site.locales);
|
|
12
|
+
const suffix = barePath === "/" ? "" : barePath;
|
|
13
|
+
const languages = {};
|
|
14
|
+
for (const available of site.locales) {
|
|
15
|
+
languages[available] = `/${available}${suffix}`;
|
|
16
|
+
}
|
|
17
|
+
languages["x-default"] = `/${site.defaultLocale}${suffix}`;
|
|
18
|
+
const index = options.robots?.index ?? true;
|
|
19
|
+
const follow = options.robots?.follow ?? true;
|
|
20
|
+
const image = options.ogImage;
|
|
21
|
+
return {
|
|
22
|
+
title: page.title,
|
|
23
|
+
description: page.description,
|
|
24
|
+
...(page.keywords === undefined ? {} : { keywords: page.keywords }),
|
|
25
|
+
authors: [{ name: site.name }],
|
|
26
|
+
creator: site.name,
|
|
27
|
+
publisher: site.name,
|
|
28
|
+
metadataBase: new URL(site.url),
|
|
29
|
+
alternates: {
|
|
30
|
+
canonical: `/${locale}${suffix}`,
|
|
31
|
+
languages,
|
|
32
|
+
},
|
|
33
|
+
openGraph: {
|
|
34
|
+
type: "website",
|
|
35
|
+
locale: options.openGraphLocale ?? `${locale}_${locale.toUpperCase()}`,
|
|
36
|
+
url: `${site.url.replace(/\/$/, "")}/${locale}${suffix}`,
|
|
37
|
+
siteName: site.name,
|
|
38
|
+
title: page.title,
|
|
39
|
+
description: page.description,
|
|
40
|
+
...(image === undefined
|
|
41
|
+
? {}
|
|
42
|
+
: {
|
|
43
|
+
images: [{ url: image.url, width: image.width, height: image.height, alt: site.name }],
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
twitter: {
|
|
47
|
+
card: "summary_large_image",
|
|
48
|
+
title: page.title,
|
|
49
|
+
description: page.description,
|
|
50
|
+
...(image === undefined ? {} : { images: [image.url] }),
|
|
51
|
+
},
|
|
52
|
+
robots: {
|
|
53
|
+
index,
|
|
54
|
+
follow,
|
|
55
|
+
googleBot: {
|
|
56
|
+
index,
|
|
57
|
+
follow,
|
|
58
|
+
"max-video-preview": -1,
|
|
59
|
+
"max-image-preview": "large",
|
|
60
|
+
"max-snippet": -1,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
|
package/dist/robots.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** robots.txt content, shaped for Next.js `MetadataRoute.Robots` routes. */
|
|
2
|
+
export interface RobotsConfig {
|
|
3
|
+
rules: {
|
|
4
|
+
userAgent: string | string[];
|
|
5
|
+
allow?: string | string[];
|
|
6
|
+
disallow?: string | string[];
|
|
7
|
+
} | Array<{
|
|
8
|
+
userAgent: string | string[];
|
|
9
|
+
allow?: string | string[];
|
|
10
|
+
disallow?: string | string[];
|
|
11
|
+
}>;
|
|
12
|
+
sitemap?: string | string[];
|
|
13
|
+
}
|
|
14
|
+
export interface BuildRobotsOptions {
|
|
15
|
+
/** Absolute site URL, e.g. `https://example.com` (trailing slash trimmed). */
|
|
16
|
+
siteUrl: string;
|
|
17
|
+
/** Extra sitemap URLs besides the default `/sitemap.xml` (e.g. a video sitemap). */
|
|
18
|
+
extraSitemaps?: string[];
|
|
19
|
+
/** Paths crawlers may not visit. Defaults to the admin area. */
|
|
20
|
+
disallow?: string[];
|
|
21
|
+
/** Paths crawlers may visit. Defaults to `/`. */
|
|
22
|
+
allow?: string[];
|
|
23
|
+
}
|
|
24
|
+
export declare function buildRobots(options: BuildRobotsOptions): RobotsConfig;
|
|
25
|
+
//# sourceMappingURL=robots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QACL,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC9B,GAAG,KAAK,CAAC;QACR,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC9B,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,YAAY,CAYrE"}
|
package/dist/robots.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function buildRobots(options) {
|
|
2
|
+
const base = options.siteUrl.replace(/\/$/, "");
|
|
3
|
+
const extra = options.extraSitemaps ?? [];
|
|
4
|
+
const sitemap = extra.length === 0 ? `${base}/sitemap.xml` : [`${base}/sitemap.xml`, ...extra];
|
|
5
|
+
return {
|
|
6
|
+
rules: {
|
|
7
|
+
userAgent: "*",
|
|
8
|
+
allow: options.allow ?? "/",
|
|
9
|
+
disallow: options.disallow ?? "/admin/",
|
|
10
|
+
},
|
|
11
|
+
sitemap,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=robots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robots.js","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,cAAc,EAAE,GAAG,KAAK,CAAC,CAAC;IAC/F,OAAO;QACL,KAAK,EAAE;YACL,SAAS,EAAE,GAAG;YACd,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG;YAC3B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS;SACxC;QACD,OAAO;KACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Sitemap entry, shaped for Next.js `MetadataRoute.Sitemap` routes. */
|
|
2
|
+
export interface SitemapEntry {
|
|
3
|
+
url: string;
|
|
4
|
+
lastModified?: string | Date;
|
|
5
|
+
changeFrequency?: "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
6
|
+
priority?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface SitemapPage {
|
|
9
|
+
/** Locale-less path: `""` for the home page, else `/path` or `/section/slug`. */
|
|
10
|
+
path: string;
|
|
11
|
+
lastModified?: string | Date;
|
|
12
|
+
changeFrequency?: SitemapEntry["changeFrequency"];
|
|
13
|
+
priority?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface BuildSitemapOptions {
|
|
16
|
+
/** Absolute site URL, e.g. `https://example.com` (trailing slash trimmed). */
|
|
17
|
+
siteUrl: string;
|
|
18
|
+
/** Locales to prefix every page with, e.g. `["en", "fr"]`. */
|
|
19
|
+
locales: string[];
|
|
20
|
+
/** Pages to list under each locale. Map CMS docs to this shape first. */
|
|
21
|
+
pages: SitemapPage[];
|
|
22
|
+
}
|
|
23
|
+
export declare function buildSitemapEntries(options: BuildSitemapOptions): SitemapEntry[];
|
|
24
|
+
//# sourceMappingURL=sitemap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yEAAyE;IACzE,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,EAAE,CAchF"}
|
package/dist/sitemap.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function buildSitemapEntries(options) {
|
|
2
|
+
const base = options.siteUrl.replace(/\/$/, "");
|
|
3
|
+
const entries = [];
|
|
4
|
+
for (const locale of options.locales) {
|
|
5
|
+
for (const page of options.pages) {
|
|
6
|
+
entries.push({
|
|
7
|
+
url: `${base}/${locale}${page.path}`,
|
|
8
|
+
...(page.lastModified === undefined ? {} : { lastModified: page.lastModified }),
|
|
9
|
+
...(page.changeFrequency === undefined ? {} : { changeFrequency: page.changeFrequency }),
|
|
10
|
+
...(page.priority === undefined ? {} : { priority: page.priority }),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return entries;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=sitemap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,mBAAmB,CAAC,OAA4B;IAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChD,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC;gBACX,GAAG,EAAE,GAAG,IAAI,IAAI,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE;gBACpC,GAAG,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC/E,GAAG,CAAC,IAAI,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC;gBACxF,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;aACpE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/slug.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Lowercase, dashed, ASCII slug (accents stripped via NFKD). */
|
|
2
|
+
export declare function normalizeSlug(value: string): string;
|
|
3
|
+
/** Draft placeholder slugs (`""`, `untitled`, `untitled-N`, `draft-N`). */
|
|
4
|
+
export declare function isDraftSlug(slug: string | null | undefined): boolean;
|
|
5
|
+
//# sourceMappingURL=slug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUnD;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAKpE"}
|
package/dist/slug.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Lowercase, dashed, ASCII slug (accents stripped via NFKD). */
|
|
2
|
+
export function normalizeSlug(value) {
|
|
3
|
+
return value
|
|
4
|
+
.normalize("NFKD")
|
|
5
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
6
|
+
.toLowerCase()
|
|
7
|
+
.replace(/\s+/g, "-")
|
|
8
|
+
.replace(/[^\w-]+/g, "")
|
|
9
|
+
.replace(/--+/g, "-")
|
|
10
|
+
.replace(/^-+/, "")
|
|
11
|
+
.replace(/-+$/, "");
|
|
12
|
+
}
|
|
13
|
+
/** Draft placeholder slugs (`""`, `untitled`, `untitled-N`, `draft-N`). */
|
|
14
|
+
export function isDraftSlug(slug) {
|
|
15
|
+
const value = (slug ?? "").trim().toLowerCase();
|
|
16
|
+
if (value.length === 0)
|
|
17
|
+
return true;
|
|
18
|
+
if (value === "untitled")
|
|
19
|
+
return true;
|
|
20
|
+
return /^untitled-\d+$/.test(value) || /^draft-\d+$/.test(value);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=slug.js.map
|
package/dist/slug.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.js","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK;SACT,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,WAAW,EAAE;SACb,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SAClB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,WAAW,CAAC,IAA+B;IACzD,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare function escapeXml(value: string): string;
|
|
2
|
+
export interface VideoSitemapEntry {
|
|
3
|
+
/** Absolute URL of the page embedding the video. */
|
|
4
|
+
pageUrl: string;
|
|
5
|
+
/** Absolute URL of the thumbnail image. */
|
|
6
|
+
thumbnailUrl: string;
|
|
7
|
+
title: string;
|
|
8
|
+
description: string;
|
|
9
|
+
/** Direct media file URL, when the video is self-hosted. */
|
|
10
|
+
contentUrl?: string;
|
|
11
|
+
/** Player page URL (embeds allowed), for hosted videos. */
|
|
12
|
+
playerUrl?: string;
|
|
13
|
+
/** Publication date, `YYYY-MM-DD`. */
|
|
14
|
+
publicationDate?: string;
|
|
15
|
+
familyFriendly?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface BuildVideoSitemapOptions {
|
|
18
|
+
videos: VideoSitemapEntry[];
|
|
19
|
+
}
|
|
20
|
+
/** Google video sitemap XML (`sitemap-video/1.1` namespace). */
|
|
21
|
+
export declare function buildVideoSitemap(options: BuildVideoSitemapOptions): string;
|
|
22
|
+
//# sourceMappingURL=video-sitemap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-sitemap.d.ts","sourceRoot":"","sources":["../src/video-sitemap.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAsB3E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function escapeXml(value) {
|
|
2
|
+
return value
|
|
3
|
+
.replace(/&/g, "&")
|
|
4
|
+
.replace(/</g, "<")
|
|
5
|
+
.replace(/>/g, ">")
|
|
6
|
+
.replace(/"/g, """)
|
|
7
|
+
.replace(/'/g, "'");
|
|
8
|
+
}
|
|
9
|
+
/** Google video sitemap XML (`sitemap-video/1.1` namespace). */
|
|
10
|
+
export function buildVideoSitemap(options) {
|
|
11
|
+
const urls = options.videos.map((video) => {
|
|
12
|
+
const tags = [
|
|
13
|
+
` <video:thumbnail_loc>${escapeXml(video.thumbnailUrl)}</video:thumbnail_loc>`,
|
|
14
|
+
` <video:title>${escapeXml(video.title)}</video:title>`,
|
|
15
|
+
` <video:description>${escapeXml(video.description)}</video:description>`,
|
|
16
|
+
];
|
|
17
|
+
if (video.contentUrl !== undefined) {
|
|
18
|
+
tags.push(` <video:content_loc>${escapeXml(video.contentUrl)}</video:content_loc>`);
|
|
19
|
+
}
|
|
20
|
+
if (video.playerUrl !== undefined) {
|
|
21
|
+
tags.push(` <video:player_loc allow_embed="yes">${escapeXml(video.playerUrl)}</video:player_loc>`);
|
|
22
|
+
}
|
|
23
|
+
if (video.publicationDate !== undefined) {
|
|
24
|
+
tags.push(` <video:publication_date>${escapeXml(video.publicationDate)}</video:publication_date>`);
|
|
25
|
+
}
|
|
26
|
+
tags.push(` <video:family_friendly>${video.familyFriendly === false ? "no" : "yes"}</video:family_friendly>`);
|
|
27
|
+
return ` <url>\n <loc>${escapeXml(video.pageUrl)}</loc>\n <video:video>\n${tags.join("\n")}\n </video:video>\n </url>`;
|
|
28
|
+
});
|
|
29
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset\n xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"\n>\n${urls.join("\n")}\n</urlset>`;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=video-sitemap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-sitemap.js","sourceRoot":"","sources":["../src/video-sitemap.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAsBD,gEAAgE;AAChE,MAAM,UAAU,iBAAiB,CAAC,OAAiC;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG;YACX,8BAA8B,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,wBAAwB;YACnF,sBAAsB,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB;YAC5D,4BAA4B,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,sBAAsB;SAC/E,CAAC;QACF,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,4BAA4B,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;QAC3F,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,IAAI,CACP,6CAA6C,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,qBAAqB,CAC7F,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,iCAAiC,SAAS,CAAC,KAAK,CAAC,eAAe,CAAC,2BAA2B,CAAC,CAAC;QAC1G,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,gCAAgC,KAAK,CAAC,cAAc,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,0BAA0B,CAAC,CAAC;QACnH,OAAO,qBAAqB,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC;IACpI,CAAC,CAAC,CAAC;IACH,OAAO,+KAA+K,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;AACrN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zedtech/zedkit-seo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
7
7
|
},
|
|
8
|
-
"description": "
|
|
8
|
+
"description": "Ship sitemaps, robots, typed JSON-LD, metadata, hreflang, slugs and llms.txt without thinking about the specs.",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"seo",
|
|
11
|
+
"sitemap",
|
|
12
|
+
"robots-txt",
|
|
13
|
+
"json-ld",
|
|
14
|
+
"structured-data",
|
|
15
|
+
"metadata",
|
|
16
|
+
"open-graph",
|
|
17
|
+
"hreflang",
|
|
18
|
+
"llms-txt",
|
|
19
|
+
"slug",
|
|
20
|
+
"nextjs",
|
|
21
|
+
"typescript"
|
|
22
|
+
],
|
|
23
|
+
"homepage": "https://github.com/zedtech-fr/zedkit/tree/main/packages/seo",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/zedtech-fr/zedkit/issues"
|
|
26
|
+
},
|
|
9
27
|
"license": "MIT",
|
|
10
28
|
"repository": {
|
|
11
29
|
"type": "git",
|