@adkinn/astro-ai-readiness 0.0.7
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/LICENSE +21 -0
- package/README.md +285 -0
- package/dist/chunk-36CGBNB5.js +104 -0
- package/dist/chunk-BDGAXJOB.js +42 -0
- package/dist/chunk-CADNETPK.js +48 -0
- package/dist/chunk-CO2DB4IE.js +141 -0
- package/dist/chunk-THSVWYUX.js +42 -0
- package/dist/chunk-V22PCH7G.js +26 -0
- package/dist/chunk-WP6D4L7O.js +48 -0
- package/dist/components/BreadcrumbSchema.astro +22 -0
- package/dist/components/CollectionSchema.astro +24 -0
- package/dist/components/FAQPageSchema.astro +24 -0
- package/dist/components/OrganizationSchema.astro +33 -0
- package/dist/components/TechArticleSchema.astro +88 -0
- package/dist/components/WebSiteSchema.astro +16 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/index.js +15 -0
- package/dist/components/types.d.ts +55 -0
- package/dist/components/types.js +0 -0
- package/dist/config.d.ts +1044 -0
- package/dist/config.js +6 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +103 -0
- package/dist/outputs/agents-md.d.ts +19 -0
- package/dist/outputs/agents-md.js +9 -0
- package/dist/outputs/llms-full.d.ts +18 -0
- package/dist/outputs/llms-full.js +9 -0
- package/dist/outputs/llms-txt.d.ts +19 -0
- package/dist/outputs/llms-txt.js +9 -0
- package/dist/outputs/mcp-json.d.ts +21 -0
- package/dist/outputs/mcp-json.js +9 -0
- package/dist/outputs/robots-txt.d.ts +20 -0
- package/dist/outputs/robots-txt.js +9 -0
- package/dist/utils/json-ld.d.ts +26 -0
- package/dist/utils/json-ld.js +7 -0
- package/package.json +76 -0
- package/schemas/mcp/v1.json +63 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
writeOutput
|
|
3
|
+
} from "./chunk-V22PCH7G.js";
|
|
4
|
+
|
|
5
|
+
// src/outputs/llms-full.ts
|
|
6
|
+
function composeLlmsFullTxt(config) {
|
|
7
|
+
const { llmsFull, llmsTxt, organization } = config;
|
|
8
|
+
const lines = [];
|
|
9
|
+
lines.push(`# ${llmsFull.title ?? organization.name}`);
|
|
10
|
+
lines.push("");
|
|
11
|
+
const summary = llmsFull.summary ?? llmsTxt?.summary;
|
|
12
|
+
if (summary) {
|
|
13
|
+
lines.push(`> ${summary}`);
|
|
14
|
+
lines.push("");
|
|
15
|
+
}
|
|
16
|
+
if (llmsFull.content) {
|
|
17
|
+
lines.push(llmsFull.content.trimEnd());
|
|
18
|
+
lines.push("");
|
|
19
|
+
}
|
|
20
|
+
if (llmsFull.sections) {
|
|
21
|
+
for (const section of llmsFull.sections) {
|
|
22
|
+
lines.push(`## ${section.title}`);
|
|
23
|
+
lines.push("");
|
|
24
|
+
lines.push(section.content.trimEnd());
|
|
25
|
+
lines.push("");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return lines.join("\n").replace(/\n+$/, "\n");
|
|
29
|
+
}
|
|
30
|
+
async function writeLlmsFullTxt(config, dir, logger) {
|
|
31
|
+
if (!config.llmsFull) return;
|
|
32
|
+
const content = composeLlmsFullTxt(
|
|
33
|
+
config
|
|
34
|
+
);
|
|
35
|
+
const target = new URL("llms-full.txt", dir);
|
|
36
|
+
await writeOutput(target, content, "llms-full.txt", logger);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
composeLlmsFullTxt,
|
|
41
|
+
writeLlmsFullTxt
|
|
42
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/outputs/write-output.ts
|
|
2
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
3
|
+
async function writeOutput(target, content, label, logger, ensureDir) {
|
|
4
|
+
if (ensureDir) {
|
|
5
|
+
await mkdir(ensureDir, { recursive: true });
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
await writeFile(target, content, { encoding: "utf-8", flag: "wx" });
|
|
9
|
+
logger.info(`wrote ${label} (${content.length} bytes)`);
|
|
10
|
+
} catch (err) {
|
|
11
|
+
const code = err?.code;
|
|
12
|
+
if (code === "EEXIST") {
|
|
13
|
+
logger.warn(
|
|
14
|
+
`${label} already exists \u2014 leaving your file untouched. Delete it if you want @adkinn/astro-ai-readiness to generate ${label}.`
|
|
15
|
+
);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
19
|
+
logger.warn(`failed to write ${label} at ${target.pathname}: ${msg}`);
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
writeOutput
|
|
26
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
writeOutput
|
|
3
|
+
} from "./chunk-V22PCH7G.js";
|
|
4
|
+
|
|
5
|
+
// src/outputs/llms-txt.ts
|
|
6
|
+
function composeLlmsTxt(config) {
|
|
7
|
+
const { llmsTxt, organization } = config;
|
|
8
|
+
const lines = [];
|
|
9
|
+
lines.push(`# ${organization.name}`);
|
|
10
|
+
lines.push("");
|
|
11
|
+
lines.push(`> ${llmsTxt.summary}`);
|
|
12
|
+
lines.push("");
|
|
13
|
+
if (llmsTxt.body) {
|
|
14
|
+
lines.push(llmsTxt.body.trimEnd());
|
|
15
|
+
lines.push("");
|
|
16
|
+
}
|
|
17
|
+
if (llmsTxt.sections && llmsTxt.sections.length > 0) {
|
|
18
|
+
for (const section of llmsTxt.sections) {
|
|
19
|
+
lines.push(`## ${section.title}`);
|
|
20
|
+
lines.push("");
|
|
21
|
+
for (const link of section.links) {
|
|
22
|
+
const desc = link.description ? `: ${link.description}` : "";
|
|
23
|
+
lines.push(`- [${link.title}](${link.url})${desc}`);
|
|
24
|
+
}
|
|
25
|
+
lines.push("");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (llmsTxt.deferTo) {
|
|
29
|
+
lines.push("---");
|
|
30
|
+
lines.push("");
|
|
31
|
+
lines.push(`Canonical reference: [${llmsTxt.deferTo.title}](${llmsTxt.deferTo.url})`);
|
|
32
|
+
lines.push("");
|
|
33
|
+
}
|
|
34
|
+
return lines.join("\n").replace(/\n+$/, "\n");
|
|
35
|
+
}
|
|
36
|
+
async function writeLlmsTxt(config, dir, logger) {
|
|
37
|
+
if (!config.llmsTxt) return;
|
|
38
|
+
const content = composeLlmsTxt(
|
|
39
|
+
config
|
|
40
|
+
);
|
|
41
|
+
const target = new URL("llms.txt", dir);
|
|
42
|
+
await writeOutput(target, content, "llms.txt", logger);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
composeLlmsTxt,
|
|
47
|
+
writeLlmsTxt
|
|
48
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { jsonLd } from '../utils/json-ld'
|
|
3
|
+
import type { BreadcrumbItem } from './types'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
items: BreadcrumbItem[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { items } = Astro.props
|
|
10
|
+
|
|
11
|
+
const bl = {
|
|
12
|
+
'@context': 'https://schema.org',
|
|
13
|
+
'@type': 'BreadcrumbList',
|
|
14
|
+
itemListElement: items.map((item, index) => ({
|
|
15
|
+
'@type': 'ListItem',
|
|
16
|
+
position: index + 1,
|
|
17
|
+
name: item.name,
|
|
18
|
+
item: item.url,
|
|
19
|
+
})),
|
|
20
|
+
}
|
|
21
|
+
---
|
|
22
|
+
{items.length > 0 && <script is:inline type="application/ld+json" set:html={jsonLd(bl)}></script>}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { config } from 'virtual:ai-readiness-config'
|
|
3
|
+
import { jsonLd } from '../utils/json-ld'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
name: string
|
|
7
|
+
url: string
|
|
8
|
+
description?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { name, url, description } = Astro.props
|
|
12
|
+
|
|
13
|
+
const cp: Record<string, unknown> = {
|
|
14
|
+
'@context': 'https://schema.org',
|
|
15
|
+
'@type': 'CollectionPage',
|
|
16
|
+
name,
|
|
17
|
+
url,
|
|
18
|
+
isPartOf: { '@id': `${config.site}#website` },
|
|
19
|
+
publisher: { '@id': `${config.site}#organization` },
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (description) cp.description = description
|
|
23
|
+
---
|
|
24
|
+
<script type="application/ld+json" is:inline set:html={jsonLd(cp)}></script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { jsonLd } from '../utils/json-ld'
|
|
3
|
+
import type { FAQItem } from './types'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
items: FAQItem[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { items } = Astro.props
|
|
10
|
+
|
|
11
|
+
const fp = {
|
|
12
|
+
'@context': 'https://schema.org',
|
|
13
|
+
'@type': 'FAQPage',
|
|
14
|
+
mainEntity: items.map((item) => ({
|
|
15
|
+
'@type': 'Question',
|
|
16
|
+
name: item.question,
|
|
17
|
+
acceptedAnswer: {
|
|
18
|
+
'@type': 'Answer',
|
|
19
|
+
text: item.answer,
|
|
20
|
+
},
|
|
21
|
+
})),
|
|
22
|
+
}
|
|
23
|
+
---
|
|
24
|
+
{items.length > 0 && <script is:inline type="application/ld+json" set:html={jsonLd(fp)}></script>}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { config } from 'virtual:ai-readiness-config'
|
|
3
|
+
import { jsonLd } from '../utils/json-ld'
|
|
4
|
+
|
|
5
|
+
const org = config.organization
|
|
6
|
+
|
|
7
|
+
type SchemaJson = Record<string, unknown>
|
|
8
|
+
|
|
9
|
+
const orgLd: SchemaJson = {
|
|
10
|
+
'@context': 'https://schema.org',
|
|
11
|
+
'@type': 'Organization',
|
|
12
|
+
'@id': `${config.site}#organization`,
|
|
13
|
+
name: org.name,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (org.url) orgLd.url = org.url
|
|
17
|
+
if (org.logo) orgLd.logo = org.logo
|
|
18
|
+
if (org.foundingDate) orgLd.foundingDate = org.foundingDate
|
|
19
|
+
if (org.knowsAbout && org.knowsAbout.length > 0) orgLd.knowsAbout = org.knowsAbout
|
|
20
|
+
if (org.areaServed) orgLd.areaServed = org.areaServed
|
|
21
|
+
|
|
22
|
+
if (org.founder) {
|
|
23
|
+
const founder: SchemaJson = {
|
|
24
|
+
'@type': 'Person',
|
|
25
|
+
name: org.founder.name,
|
|
26
|
+
}
|
|
27
|
+
if (org.founder.jobTitle) founder.jobTitle = org.founder.jobTitle
|
|
28
|
+
if (org.founder.description) founder.description = org.founder.description
|
|
29
|
+
if (org.founder.sameAs && org.founder.sameAs.length > 0) founder.sameAs = org.founder.sameAs
|
|
30
|
+
orgLd.founder = founder
|
|
31
|
+
}
|
|
32
|
+
---
|
|
33
|
+
<script type="application/ld+json" is:inline set:html={jsonLd(orgLd)}></script>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { config } from 'virtual:ai-readiness-config'
|
|
3
|
+
import { jsonLd } from '../utils/json-ld'
|
|
4
|
+
import type { TechArticleAuthor, TechArticleImage } from './types'
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
// Required
|
|
8
|
+
headline: string
|
|
9
|
+
description: string
|
|
10
|
+
datePublished: string
|
|
11
|
+
|
|
12
|
+
// Optional — common
|
|
13
|
+
dateModified?: string
|
|
14
|
+
author?: TechArticleAuthor
|
|
15
|
+
image?: TechArticleImage
|
|
16
|
+
url?: string
|
|
17
|
+
|
|
18
|
+
// Optional — Schema.org TechArticle extensions
|
|
19
|
+
articleSection?: string
|
|
20
|
+
keywords?: string[]
|
|
21
|
+
proficiencyLevel?: string
|
|
22
|
+
dependencies?: string[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
headline,
|
|
27
|
+
description,
|
|
28
|
+
datePublished,
|
|
29
|
+
dateModified,
|
|
30
|
+
author,
|
|
31
|
+
image,
|
|
32
|
+
url,
|
|
33
|
+
articleSection,
|
|
34
|
+
keywords,
|
|
35
|
+
proficiencyLevel,
|
|
36
|
+
dependencies,
|
|
37
|
+
} = Astro.props
|
|
38
|
+
|
|
39
|
+
// D-21: author defaults to a Person synthesized from config.organization.founder.
|
|
40
|
+
// Founder-precondition guard: if author is omitted AND founder is unset, fail loudly
|
|
41
|
+
// at build time rather than tighten the global schema (which would break consumers
|
|
42
|
+
// who don't use TechArticle and don't set founder).
|
|
43
|
+
const founder = config.organization.founder
|
|
44
|
+
let resolvedAuthor: TechArticleAuthor
|
|
45
|
+
if (author) {
|
|
46
|
+
resolvedAuthor = author
|
|
47
|
+
} else {
|
|
48
|
+
if (!founder) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
'TechArticleSchema: `author` prop omitted and `config.organization.founder` ' +
|
|
51
|
+
'is unset. Either pass an explicit `author` prop, or add a `founder` block to ' +
|
|
52
|
+
'the `organization` config in your `aiReadiness({...})` integration call.'
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
resolvedAuthor = {
|
|
56
|
+
name: founder.name,
|
|
57
|
+
...(founder.sameAs && founder.sameAs[0] && { url: founder.sameAs[0] }),
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const resolvedImage =
|
|
62
|
+
typeof image === 'string'
|
|
63
|
+
? { '@type': 'ImageObject', url: image }
|
|
64
|
+
: image
|
|
65
|
+
? { '@type': 'ImageObject', ...image }
|
|
66
|
+
: undefined
|
|
67
|
+
|
|
68
|
+
const resolvedUrl = url ?? new URL(Astro.url.pathname, config.site).toString()
|
|
69
|
+
|
|
70
|
+
const ta: Record<string, unknown> = {
|
|
71
|
+
'@context': 'https://schema.org',
|
|
72
|
+
'@type': 'TechArticle',
|
|
73
|
+
headline,
|
|
74
|
+
description,
|
|
75
|
+
datePublished,
|
|
76
|
+
dateModified: dateModified ?? datePublished,
|
|
77
|
+
author: { '@type': 'Person', ...resolvedAuthor },
|
|
78
|
+
publisher: { '@id': `${config.site}#organization` },
|
|
79
|
+
url: resolvedUrl,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (resolvedImage) ta.image = resolvedImage
|
|
83
|
+
if (articleSection) ta.articleSection = articleSection
|
|
84
|
+
if (keywords && keywords.length > 0) ta.keywords = keywords.join(', ')
|
|
85
|
+
if (proficiencyLevel) ta.proficiencyLevel = proficiencyLevel
|
|
86
|
+
if (dependencies && dependencies.length > 0) ta.dependencies = dependencies.join(', ')
|
|
87
|
+
---
|
|
88
|
+
<script is:inline type="application/ld+json" set:html={jsonLd(ta)}></script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { config } from 'virtual:ai-readiness-config'
|
|
3
|
+
import { jsonLd } from '../utils/json-ld'
|
|
4
|
+
|
|
5
|
+
const ws: Record<string, unknown> = {
|
|
6
|
+
'@context': 'https://schema.org',
|
|
7
|
+
'@type': 'WebSite',
|
|
8
|
+
'@id': `${config.site}#website`,
|
|
9
|
+
name: config.webSite?.name ?? config.organization.name,
|
|
10
|
+
url: config.site,
|
|
11
|
+
publisher: { '@id': `${config.site}#organization` },
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (config.webSite?.description) ws.description = config.webSite.description
|
|
15
|
+
---
|
|
16
|
+
<script type="application/ld+json" is:inline set:html={jsonLd(ws)}></script>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as OrganizationSchema } from './OrganizationSchema.astro';
|
|
2
|
+
export { default as WebSiteSchema } from './WebSiteSchema.astro';
|
|
3
|
+
export { default as CollectionSchema } from './CollectionSchema.astro';
|
|
4
|
+
export { default as BreadcrumbSchema } from './BreadcrumbSchema.astro';
|
|
5
|
+
export { default as FAQPageSchema } from './FAQPageSchema.astro';
|
|
6
|
+
export { default as TechArticleSchema } from './TechArticleSchema.astro';
|
|
7
|
+
export { BreadcrumbItem, FAQItem, TechArticleAuthor, TechArticleImage } from './types.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/components/index.ts
|
|
2
|
+
import { default as default2 } from "./OrganizationSchema.astro";
|
|
3
|
+
import { default as default3 } from "./WebSiteSchema.astro";
|
|
4
|
+
import { default as default4 } from "./CollectionSchema.astro";
|
|
5
|
+
import { default as default5 } from "./BreadcrumbSchema.astro";
|
|
6
|
+
import { default as default6 } from "./FAQPageSchema.astro";
|
|
7
|
+
import { default as default7 } from "./TechArticleSchema.astro";
|
|
8
|
+
export {
|
|
9
|
+
default5 as BreadcrumbSchema,
|
|
10
|
+
default4 as CollectionSchema,
|
|
11
|
+
default6 as FAQPageSchema,
|
|
12
|
+
default2 as OrganizationSchema,
|
|
13
|
+
default7 as TechArticleSchema,
|
|
14
|
+
default3 as WebSiteSchema
|
|
15
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import './OrganizationSchema.astro';
|
|
2
|
+
import './WebSiteSchema.astro';
|
|
3
|
+
import './CollectionSchema.astro';
|
|
4
|
+
import './BreadcrumbSchema.astro';
|
|
5
|
+
import './FAQPageSchema.astro';
|
|
6
|
+
import './TechArticleSchema.astro';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Shared prop-shape types for components that need declarable interfaces
|
|
10
|
+
* (items-array element shapes, heavy-props nested-object shapes).
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
* Consumers should import from the barrel:
|
|
14
|
+
* `import type { BreadcrumbItem, FAQItem, TechArticleAuthor, TechArticleImage } from '@adkinn/astro-ai-readiness/components'`
|
|
15
|
+
* The `/components/types` subpath is intentionally not exposed in
|
|
16
|
+
* `package.json.exports` — deep-importing
|
|
17
|
+
* `@adkinn/astro-ai-readiness/components/types` will fail with
|
|
18
|
+
* `ERR_PACKAGE_PATH_NOT_EXPORTED`. The file ships as a build artifact
|
|
19
|
+
* so internal relative imports (`./types`) work; the barrel is the
|
|
20
|
+
* public surface. Same pattern as `src/utils/json-ld.ts`.
|
|
21
|
+
*
|
|
22
|
+
* `.astro` files are externalized in `tsup.config.ts`, so their declaration
|
|
23
|
+
* types don't ship via tsup's `dts: true`. Interface types must live in a
|
|
24
|
+
* `.ts` file. This module is the single home for prop shapes — items-array
|
|
25
|
+
* elements (`BreadcrumbItem`, `FAQItem`) and heavy-props nested objects
|
|
26
|
+
* (`TechArticleAuthor`, `TechArticleImage`) — that both the component
|
|
27
|
+
* frontmatter and the package barrel re-export.
|
|
28
|
+
*
|
|
29
|
+
* Components import via relative path (`./types`); the barrel re-exports
|
|
30
|
+
* for consumer-side use.
|
|
31
|
+
*/
|
|
32
|
+
interface BreadcrumbItem {
|
|
33
|
+
name: string;
|
|
34
|
+
url: string;
|
|
35
|
+
}
|
|
36
|
+
interface FAQItem {
|
|
37
|
+
question: string;
|
|
38
|
+
answer: string;
|
|
39
|
+
}
|
|
40
|
+
interface TechArticleAuthor {
|
|
41
|
+
name: string;
|
|
42
|
+
url?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* URL string is the common case; object form supports width/height/caption
|
|
46
|
+
* when the consumer wants the richer Schema.org ImageObject shape.
|
|
47
|
+
*/
|
|
48
|
+
type TechArticleImage = string | {
|
|
49
|
+
url: string;
|
|
50
|
+
width?: number;
|
|
51
|
+
height?: number;
|
|
52
|
+
caption?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type { BreadcrumbItem, FAQItem, TechArticleAuthor, TechArticleImage };
|
|
File without changes
|