@actuate-media/plugin-seo 0.0.14 → 0.0.16
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/CHANGELOG.md +50 -0
- package/dist/__tests__/audit-fixes.test.d.ts +2 -0
- package/dist/__tests__/audit-fixes.test.d.ts.map +1 -0
- package/dist/__tests__/audit-fixes.test.js +162 -0
- package/dist/__tests__/audit-fixes.test.js.map +1 -0
- package/dist/index.d.ts +7 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/link-health/index.d.ts +23 -3
- package/dist/link-health/index.d.ts.map +1 -1
- package/dist/link-health/index.js +95 -31
- package/dist/link-health/index.js.map +1 -1
- package/dist/robots/index.d.ts.map +1 -1
- package/dist/robots/index.js +10 -11
- package/dist/robots/index.js.map +1 -1
- package/dist/schema/composer.d.ts +12 -0
- package/dist/schema/composer.d.ts.map +1 -1
- package/dist/schema/composer.js +12 -0
- package/dist/schema/composer.js.map +1 -1
- package/dist/schema/validator.d.ts +12 -0
- package/dist/schema/validator.d.ts.map +1 -1
- package/dist/schema/validator.js +41 -0
- package/dist/schema/validator.js.map +1 -1
- package/dist/sitemap/index.d.ts +24 -1
- package/dist/sitemap/index.d.ts.map +1 -1
- package/dist/sitemap/index.js +37 -4
- package/dist/sitemap/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# @actuate-media/plugin-seo
|
|
2
2
|
|
|
3
|
+
## 0.0.16
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c231dd0: Add `definePlugin` and migrate all 10 plugins onto the canonical `PluginDefinition` contract.
|
|
8
|
+
|
|
9
|
+
cms-core already exported `PluginDefinition`, but every plugin hand-rolled a
|
|
10
|
+
local `ActuatePlugin` interface — a lossy subset that dropped `version`/`init`
|
|
11
|
+
and, in blocks/email/ai, widened hook payloads to `unknown[]`/`event: string`.
|
|
12
|
+
That's copy-paste drift with no shared source of truth.
|
|
13
|
+
|
|
14
|
+
`cms-core` now exports `definePlugin(plugin: PluginDefinition)` (an identity
|
|
15
|
+
helper like `defineConfig`), and each plugin imports the canonical type instead
|
|
16
|
+
of its own: the local `ActuatePlugin` interfaces are deleted, factory return
|
|
17
|
+
types are `PluginDefinition`, and the widened `hooks.ts` types are retyped as
|
|
18
|
+
`PluginHook[]`. Type-only change — no runtime behavior, plugin `name`, or config
|
|
19
|
+
options changed. Net −69 lines.
|
|
20
|
+
|
|
21
|
+
- 325694f: Import `definePlugin` from the lightweight `@actuate-media/cms-core/config`
|
|
22
|
+
entry instead of the barrel.
|
|
23
|
+
|
|
24
|
+
The plugin-definition migration imported the `definePlugin` **value** from
|
|
25
|
+
`@actuate-media/cms-core`, which pulls the entire cms-core barrel (graphql,
|
|
26
|
+
sharp, sentry, codegen) into every plugin's runtime — bundle bloat for
|
|
27
|
+
consumers and, under parallel test load, a timeout. The `/config` subpath exists
|
|
28
|
+
precisely to avoid the barrel. Types stay as erased `import type`, so nothing
|
|
29
|
+
heavy is loaded. No API or behavior change.
|
|
30
|
+
|
|
31
|
+
## 0.0.15
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- cc18833: SEO audit remediation — 47 verified fixes across the SEO system.
|
|
36
|
+
|
|
37
|
+
Highlights: redirect middleware no longer excludes legacy `.html/.php/.aspx`
|
|
38
|
+
URLs (migrations); robots.txt now `Allow`s the default OG image (`/api/cms/og.png`)
|
|
39
|
+
so social shares render; RSS always emits the mandatory channel `<description>`;
|
|
40
|
+
structured-data auto-detection no longer emits invalid `Review/Event/JobPosting`
|
|
41
|
+
(required fields enforced or the node is suppressed) and no longer mis-types
|
|
42
|
+
collections by substring (`newsletters`→NewsArticle etc.); the sitemap endpoint
|
|
43
|
+
no longer selects full document JSON for up to 45k rows; IndexNow submits on
|
|
44
|
+
every publish instead of being swallowed by the sitemap debounce; the exported
|
|
45
|
+
`renderJsonLdScript()` now escapes `<`; the editor no longer shows two
|
|
46
|
+
conflicting scores and the Content-tab analysis now understands section-built
|
|
47
|
+
pages; plus pagination `rel`/canonical, `og:locale` normalization + alternates,
|
|
48
|
+
canonical absolutization, VideoObject/Product/WebSite-SearchAction builders,
|
|
49
|
+
redirect loop/case handling, plugin-seo sitemap caps + real `lastmod`, and
|
|
50
|
+
plugin link-health routed through `safeFetch`. Adds several new exports on
|
|
51
|
+
`@actuate-media/cms-core` (e.g. `buildVideoObjectSchema`, `buildProductSchema`).
|
|
52
|
+
|
|
3
53
|
## 0.0.14
|
|
4
54
|
|
|
5
55
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-fixes.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/audit-fixes.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
|
+
import { generateSitemapIndex, generateCollectionSitemap, SITEMAP_MAX_URLS, } from '../sitemap/index.js';
|
|
3
|
+
import { generateRobotsTxt } from '../robots/index.js';
|
|
4
|
+
import { validateSchemaGraph } from '../schema/validator.js';
|
|
5
|
+
import { composeAndValidateSchema } from '../schema/composer.js';
|
|
6
|
+
import { detectRedirectChains, detectBrokenLinks, MAX_LINKS } from '../link-health/index.js';
|
|
7
|
+
import { AI_TRAINING_BOTS, AI_RETRIEVAL_BOTS } from '@actuate-media/cms-core';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Finding 1 — sitemap 50k/50MB cap + stable index lastmod + Yoast child URLs
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
describe('sitemap generators (finding 1)', () => {
|
|
12
|
+
it('does not stamp a churning Date.now() lastmod on the index', () => {
|
|
13
|
+
const out = generateSitemapIndex(['posts'], 'https://example.com');
|
|
14
|
+
expect(out).not.toContain('<lastmod>');
|
|
15
|
+
// Yoast-style child URL, aligned with the core route.
|
|
16
|
+
expect(out).toContain('<loc>https://example.com/posts-sitemap.xml</loc>');
|
|
17
|
+
});
|
|
18
|
+
it('derives index lastmod from the collection newest-entry timestamp', () => {
|
|
19
|
+
const out = generateSitemapIndex([{ slug: 'posts', type: 'post', lastmod: '2026-01-02T03:04:05.000Z' }], 'https://example.com');
|
|
20
|
+
expect(out).toContain('<lastmod>2026-01-02T03:04:05.000Z</lastmod>');
|
|
21
|
+
// `post` Yoast base name for the canonical posts collection.
|
|
22
|
+
expect(out).toContain('<loc>https://example.com/post-sitemap.xml</loc>');
|
|
23
|
+
});
|
|
24
|
+
it('is deterministic across calls (same input -> same output)', () => {
|
|
25
|
+
const cfg = [{ slug: 'pages', type: 'page', lastmod: '2026-01-01T00:00:00.000Z' }];
|
|
26
|
+
expect(generateSitemapIndex(cfg, 'https://x.com')).toBe(generateSitemapIndex(cfg, 'https://x.com'));
|
|
27
|
+
});
|
|
28
|
+
it('renders a normal collection sitemap under the cap', () => {
|
|
29
|
+
const entries = [{ loc: 'a', lastmod: '2026-01-01' }, { loc: 'b' }];
|
|
30
|
+
const xml = generateCollectionSitemap(entries, 'https://example.com');
|
|
31
|
+
expect(xml).toContain('<loc>https://example.com/a</loc>');
|
|
32
|
+
expect(xml).toContain('<loc>https://example.com/b</loc>');
|
|
33
|
+
});
|
|
34
|
+
it('throws past the 50,000-URL limit instead of emitting an oversized file', () => {
|
|
35
|
+
const entries = Array.from({ length: SITEMAP_MAX_URLS + 1 }, (_, i) => ({
|
|
36
|
+
loc: `p${i}`,
|
|
37
|
+
}));
|
|
38
|
+
expect(() => generateCollectionSitemap(entries, 'https://example.com')).toThrow(RangeError);
|
|
39
|
+
});
|
|
40
|
+
it('accepts exactly the 50,000-URL limit', () => {
|
|
41
|
+
const entries = Array.from({ length: SITEMAP_MAX_URLS }, (_, i) => ({
|
|
42
|
+
loc: `p${i}`,
|
|
43
|
+
}));
|
|
44
|
+
expect(() => generateCollectionSitemap(entries, 'https://example.com')).not.toThrow();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Finding 2 — validateSchema wired into the compose path (via @graph adapter)
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
describe('schema validation wiring (finding 2)', () => {
|
|
51
|
+
it('validateSchemaGraph flags a node in a @graph missing required fields', () => {
|
|
52
|
+
const graph = {
|
|
53
|
+
'@context': 'https://schema.org',
|
|
54
|
+
'@graph': [
|
|
55
|
+
{ '@type': 'Article', headline: 'Hi', author: 'Jane', datePublished: '2026-01-01' },
|
|
56
|
+
{ '@type': 'Review', reviewRating: { ratingValue: 5 } }, // missing itemReviewed, author
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
const result = validateSchemaGraph(graph);
|
|
60
|
+
expect(result.valid).toBe(false);
|
|
61
|
+
const fields = result.errors.map((e) => e.field);
|
|
62
|
+
expect(fields).toContain('@graph[1].itemReviewed');
|
|
63
|
+
expect(fields).toContain('@graph[1].author');
|
|
64
|
+
// The valid Article node (node 0) has no error-severity findings.
|
|
65
|
+
const node0Errors = result.errors.filter((e) => e.field.startsWith('@graph[0].') && e.severity === 'error');
|
|
66
|
+
expect(node0Errors).toEqual([]);
|
|
67
|
+
});
|
|
68
|
+
it('validateSchemaGraph does not flag nodes for a wrapper-provided @context', () => {
|
|
69
|
+
const graph = {
|
|
70
|
+
'@context': 'https://schema.org',
|
|
71
|
+
'@graph': [{ '@type': 'Organization', name: 'Acme' }],
|
|
72
|
+
};
|
|
73
|
+
const result = validateSchemaGraph(graph);
|
|
74
|
+
expect(result.errors.some((e) => e.field.endsWith('@context'))).toBe(false);
|
|
75
|
+
expect(result.valid).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
it('composeAndValidateSchema exercises the validator on the emitted node', () => {
|
|
78
|
+
const { schema, validation } = composeAndValidateSchema('Event', { name: 'Launch' });
|
|
79
|
+
expect(schema['@type']).toBe('Event');
|
|
80
|
+
// Missing startDate -> flagged, not silently shipped.
|
|
81
|
+
expect(validation.valid).toBe(false);
|
|
82
|
+
expect(validation.errors.some((e) => e.field === 'startDate')).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Finding 3 — robots delegates to the canonical cms-core AI bot taxonomy
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
describe('generateRobotsTxt AI bots (finding 3)', () => {
|
|
89
|
+
it('blocks the full canonical training + retrieval taxonomy', () => {
|
|
90
|
+
const txt = generateRobotsTxt({ blockAIBots: true });
|
|
91
|
+
for (const bot of [...AI_TRAINING_BOTS, ...AI_RETRIEVAL_BOTS]) {
|
|
92
|
+
expect(txt).toContain(`User-agent: ${bot}`);
|
|
93
|
+
}
|
|
94
|
+
// 2026 bots that the stale hardcoded list of 8 was missing.
|
|
95
|
+
for (const bot of ['PerplexityBot', 'Amazonbot', 'Applebot-Extended', 'OAI-SearchBot']) {
|
|
96
|
+
expect(txt).toContain(`User-agent: ${bot}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
it('does not emit AI bot rules when blockAIBots is off', () => {
|
|
100
|
+
const txt = generateRobotsTxt({ blockAIBots: false });
|
|
101
|
+
expect(txt).not.toContain('GPTBot');
|
|
102
|
+
});
|
|
103
|
+
it('dedupes an additional bot that repeats a canonical token', () => {
|
|
104
|
+
const txt = generateRobotsTxt({ blockAIBots: true, additionalAIBots: ['GPTBot'] });
|
|
105
|
+
expect(txt.match(/User-agent: GPTBot/g)?.length).toBe(1);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Finding 4 — redirect loops distinguished from terminating chains
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
describe('detectRedirectChains (finding 4)', () => {
|
|
112
|
+
it('labels a cycle as a loop, not a chain', () => {
|
|
113
|
+
const result = detectRedirectChains([
|
|
114
|
+
{ from: 'A', to: 'B' },
|
|
115
|
+
{ from: 'B', to: 'A' },
|
|
116
|
+
]);
|
|
117
|
+
expect(result).toHaveLength(1);
|
|
118
|
+
expect(result[0].kind).toBe('loop');
|
|
119
|
+
expect(result[0].chain).toEqual(['A', 'B', 'A']);
|
|
120
|
+
});
|
|
121
|
+
it('labels a terminating multi-hop redirect as a chain', () => {
|
|
122
|
+
const result = detectRedirectChains([
|
|
123
|
+
{ from: 'A', to: 'B' },
|
|
124
|
+
{ from: 'B', to: 'C' },
|
|
125
|
+
]);
|
|
126
|
+
expect(result).toHaveLength(1);
|
|
127
|
+
expect(result[0].kind).toBe('chain');
|
|
128
|
+
expect(result[0].finalUrl).toBe('C');
|
|
129
|
+
expect(result[0].length).toBe(2);
|
|
130
|
+
});
|
|
131
|
+
it('does not emit a chain for a single hop', () => {
|
|
132
|
+
expect(detectRedirectChains([{ from: 'A', to: 'B' }])).toEqual([]);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
// Finding 5 — broken-link checker uses safeFetch, caps links, keeps timeout
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
describe('detectBrokenLinks (finding 5)', () => {
|
|
139
|
+
afterEach(() => {
|
|
140
|
+
vi.restoreAllMocks();
|
|
141
|
+
});
|
|
142
|
+
it('blocks SSRF targets (loopback) via safeFetch instead of raw fetch', async () => {
|
|
143
|
+
const fetchSpy = vi.spyOn(globalThis, 'fetch');
|
|
144
|
+
const html = '<a href="http://127.0.0.1/admin">x</a>';
|
|
145
|
+
const results = await detectBrokenLinks(html, 'https://example.com');
|
|
146
|
+
expect(results).toHaveLength(1);
|
|
147
|
+
expect(results[0].status).toBe('blocked');
|
|
148
|
+
// safeFetch's SSRF preflight rejects before any network fetch is issued.
|
|
149
|
+
expect(fetchSpy).not.toHaveBeenCalled();
|
|
150
|
+
});
|
|
151
|
+
it('caps the number of links scanned at MAX_LINKS', async () => {
|
|
152
|
+
const fetchSpy = vi.spyOn(globalThis, 'fetch');
|
|
153
|
+
// Distinct loopback paths: rejected by safeFetch's synchronous IP-literal
|
|
154
|
+
// check (no DNS, no network), so this exercises the cap without hanging.
|
|
155
|
+
const html = Array.from({ length: MAX_LINKS + 50 }, (_, i) => `<a href="http://127.0.0.1/p${i}">x</a>`).join('');
|
|
156
|
+
const results = await detectBrokenLinks(html, 'https://example.com');
|
|
157
|
+
expect(results).toHaveLength(MAX_LINKS);
|
|
158
|
+
expect(results.every((r) => r.status === 'blocked')).toBe(true);
|
|
159
|
+
expect(fetchSpy).not.toHaveBeenCalled();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
//# sourceMappingURL=audit-fixes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-fixes.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-fixes.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAC5D,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,gBAAgB,GAEjB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAE7E,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAC9E,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC,CAAA;QAClE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;QACtC,sDAAsD;QACtD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kDAAkD,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,GAAG,GAAG,oBAAoB,CAC9B,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,EACtE,qBAAqB,CACtB,CAAA;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,6CAA6C,CAAC,CAAA;QACpE,6DAA6D;QAC7D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,iDAAiD,CAAC,CAAA;IAC1E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAA;QAC3F,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CACrD,oBAAoB,CAAC,GAAG,EAAE,eAAe,CAAC,CAC3C,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,OAAO,GAAmB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;QACnF,MAAM,GAAG,GAAG,yBAAyB,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAA;QACrE,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAA;QACzD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,MAAM,OAAO,GAAmB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACtF,GAAG,EAAE,IAAI,CAAC,EAAE;SACb,CAAC,CAAC,CAAA;QACH,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAC7F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,OAAO,GAAmB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAClF,GAAG,EAAE,IAAI,CAAC,EAAE;SACb,CAAC,CAAC,CAAA;QACH,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IACvF,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,8EAA8E;AAC9E,8EAA8E;AAC9E,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,KAAK,GAAG;YACZ,UAAU,EAAE,oBAAoB;YAChC,QAAQ,EAAE;gBACR,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE;gBACnF,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,+BAA+B;aACzF;SACF,CAAA;QACD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;QACzC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAA;QAC5C,kEAAkE;QAClE,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,CAClE,CAAA;QACD,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,KAAK,GAAG;YACZ,UAAU,EAAE,oBAAoB;YAChC,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACtD,CAAA;QACD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;QACzC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3E,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,wBAAwB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QACpF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACrC,sDAAsD;QACtD,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,yEAAyE;AACzE,8EAA8E;AAC9E,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,GAAG,GAAG,iBAAiB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;QACpD,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,gBAAgB,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC;YAC9D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,eAAe,GAAG,EAAE,CAAC,CAAA;QAC7C,CAAC;QACD,4DAA4D;QAC5D,KAAK,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,WAAW,EAAE,mBAAmB,EAAE,eAAe,CAAC,EAAE,CAAC;YACvF,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,eAAe,GAAG,EAAE,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,GAAG,GAAG,iBAAiB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAA;QACrD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,GAAG,GAAG,iBAAiB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QAClF,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,mEAAmE;AACnE,8EAA8E;AAC9E,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,MAAM,GAAG,oBAAoB,CAAC;YAClC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE;YACtB,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE;SACvB,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,MAAM,GAAG,oBAAoB,CAAC;YAClC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE;YACtB,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE;SACvB,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,oBAAoB,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAC9E,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,eAAe,EAAE,CAAA;IACtB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QAC9C,MAAM,IAAI,GAAG,wCAAwC,CAAA;QACrD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAA;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC1C,yEAAyE;QACzE,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QAC9C,0EAA0E;QAC1E,yEAAyE;QACzE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CACrB,EAAE,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,EAC1B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,8BAA8B,CAAC,SAAS,CACnD,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACV,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAA;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;QACvC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/D,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
export interface ActuatePlugin {
|
|
3
|
-
name: string;
|
|
4
|
-
fields?: Record<string, FieldDefinition>;
|
|
5
|
-
collections?: Record<string, CollectionDefinition>;
|
|
6
|
-
adminNavItems?: Array<{
|
|
7
|
-
label: string;
|
|
8
|
-
icon: string;
|
|
9
|
-
path: string;
|
|
10
|
-
}>;
|
|
11
|
-
hooks?: PluginHook[];
|
|
12
|
-
}
|
|
1
|
+
import { type PluginDefinition } from '@actuate-media/cms-core/config';
|
|
13
2
|
export interface SEOPluginConfig {
|
|
14
3
|
sitemap?: {
|
|
15
4
|
enabled?: boolean;
|
|
@@ -45,21 +34,22 @@ export interface SEOPluginConfig {
|
|
|
45
34
|
};
|
|
46
35
|
}
|
|
47
36
|
/** Creates an SEO plugin instance for Actuate CMS. */
|
|
48
|
-
export declare function seoPlugin(config?: SEOPluginConfig):
|
|
37
|
+
export declare function seoPlugin(config?: SEOPluginConfig): PluginDefinition;
|
|
49
38
|
export { seoFields } from './fields.js';
|
|
50
39
|
export { seoCollections } from './collections.js';
|
|
51
40
|
export { seoHooks } from './hooks.js';
|
|
52
41
|
export { detectSchemaType } from './schema/auto-detect.js';
|
|
53
|
-
export { composeSchema } from './schema/composer.js';
|
|
54
|
-
export { validateSchema } from './schema/validator.js';
|
|
42
|
+
export { composeSchema, composeAndValidateSchema } from './schema/composer.js';
|
|
43
|
+
export { validateSchema, validateSchemaGraph } from './schema/validator.js';
|
|
55
44
|
export type { ValidationResult } from './schema/validator.js';
|
|
56
|
-
export { generateSitemapIndex, generateCollectionSitemap, generateImageSitemap, generateVideoSitemap, generateNewsSitemap, generateHreflangSitemap, buildDocumentUrl, } from './sitemap/index.js';
|
|
45
|
+
export { generateSitemapIndex, generateCollectionSitemap, generateImageSitemap, generateVideoSitemap, generateNewsSitemap, generateHreflangSitemap, buildDocumentUrl, SITEMAP_MAX_URLS, SITEMAP_MAX_BYTES, } from './sitemap/index.js';
|
|
57
46
|
export type { SitemapEntry, ImageSitemapEntry, VideoSitemapEntry, NewsSitemapEntry, HreflangEntry, CollectionSitemapConfig, } from './sitemap/index.js';
|
|
58
47
|
export { generateRobotsTxt } from './robots/index.js';
|
|
59
48
|
export type { RobotsConfig } from './robots/index.js';
|
|
60
49
|
export { generateOGImage } from './og-image/index.js';
|
|
61
50
|
export type { OGImageOptions } from './og-image/index.js';
|
|
62
|
-
export { detectBrokenLinks, detectOrphanPages, detectRedirectChains } from './link-health/index.js';
|
|
51
|
+
export { detectBrokenLinks, detectOrphanPages, detectRedirectChains, MAX_LINKS, } from './link-health/index.js';
|
|
52
|
+
export type { LinkHealthResult, RedirectChain } from './link-health/index.js';
|
|
63
53
|
export { detectDuplicates, suggestCanonical } from './canonical/index.js';
|
|
64
54
|
export type { DuplicateGroup } from './canonical/index.js';
|
|
65
55
|
export { SEOPanel } from './admin/SEOPanel.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAKpF,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;QAC7B,eAAe,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;QAC3F,eAAe,CAAC,EAAE,MAAM,CAAA;KACzB,CAAA;IACD,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,eAAe,CAAC,EAAE,KAAK,CAAC;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAA;KACtF,CAAA;IACD,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;QAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,UAAU,CAAC,EAAE;QACX,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IACD,cAAc,CAAC,EAAE;QACf,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,mBAAmB,CAAC,EAAE;YACpB,IAAI,EAAE,MAAM,CAAA;YACZ,GAAG,EAAE,MAAM,CAAA;YACX,IAAI,CAAC,EAAE,MAAM,CAAA;SACd,CAAA;KACF,CAAA;CACF;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,MAAM,GAAE,eAAoB,GAAG,gBAAgB,CAexE;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3E,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,uBAAuB,GACxB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,GACV,MAAM,wBAAwB,CAAA;AAC/B,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACzE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAExD,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,gBAAgB,GACjB,MAAM,sBAAsB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { definePlugin } from '@actuate-media/cms-core/config';
|
|
1
2
|
import { seoFields } from './fields.js';
|
|
2
3
|
import { seoCollections } from './collections.js';
|
|
3
4
|
import { seoHooks } from './hooks.js';
|
|
4
5
|
/** Creates an SEO plugin instance for Actuate CMS. */
|
|
5
6
|
export function seoPlugin(config = {}) {
|
|
6
|
-
return {
|
|
7
|
+
return definePlugin({
|
|
7
8
|
name: 'plugin-seo',
|
|
8
9
|
fields: { ...seoFields },
|
|
9
10
|
collections: { ...seoCollections },
|
|
@@ -16,18 +17,18 @@ export function seoPlugin(config = {}) {
|
|
|
16
17
|
...hook,
|
|
17
18
|
_pluginConfig: config,
|
|
18
19
|
})),
|
|
19
|
-
};
|
|
20
|
+
});
|
|
20
21
|
}
|
|
21
22
|
export { seoFields } from './fields.js';
|
|
22
23
|
export { seoCollections } from './collections.js';
|
|
23
24
|
export { seoHooks } from './hooks.js';
|
|
24
25
|
export { detectSchemaType } from './schema/auto-detect.js';
|
|
25
|
-
export { composeSchema } from './schema/composer.js';
|
|
26
|
-
export { validateSchema } from './schema/validator.js';
|
|
27
|
-
export { generateSitemapIndex, generateCollectionSitemap, generateImageSitemap, generateVideoSitemap, generateNewsSitemap, generateHreflangSitemap, buildDocumentUrl, } from './sitemap/index.js';
|
|
26
|
+
export { composeSchema, composeAndValidateSchema } from './schema/composer.js';
|
|
27
|
+
export { validateSchema, validateSchemaGraph } from './schema/validator.js';
|
|
28
|
+
export { generateSitemapIndex, generateCollectionSitemap, generateImageSitemap, generateVideoSitemap, generateNewsSitemap, generateHreflangSitemap, buildDocumentUrl, SITEMAP_MAX_URLS, SITEMAP_MAX_BYTES, } from './sitemap/index.js';
|
|
28
29
|
export { generateRobotsTxt } from './robots/index.js';
|
|
29
30
|
export { generateOGImage } from './og-image/index.js';
|
|
30
|
-
export { detectBrokenLinks, detectOrphanPages, detectRedirectChains } from './link-health/index.js';
|
|
31
|
+
export { detectBrokenLinks, detectOrphanPages, detectRedirectChains, MAX_LINKS, } from './link-health/index.js';
|
|
31
32
|
export { detectDuplicates, suggestCanonical } from './canonical/index.js';
|
|
32
33
|
export { SEOPanel } from './admin/SEOPanel.js';
|
|
33
34
|
export { GooglePreview } from './admin/GooglePreview.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyB,MAAM,gCAAgC,CAAA;AACpF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAiCrC,sDAAsD;AACtD,MAAM,UAAU,SAAS,CAAC,SAA0B,EAAE;IACpD,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,EAAE,GAAG,SAAS,EAAE;QACxB,WAAW,EAAE,EAAE,GAAG,cAAc,EAAE;QAClC,aAAa,EAAE;YACb,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE;YACvD,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE;YACvD,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE;SACjE;QACD,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7B,GAAG,IAAI;YACP,aAAa,EAAE,MAAM;SACtB,CAAC,CAA8B;KACjC,CAAC,CAAA;AACJ,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAE3E,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAS3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,GACV,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export interface LinkHealthResult {
|
|
2
2
|
url: string;
|
|
3
|
-
status: 'ok' | 'broken' | 'redirect' | 'timeout' | 'error';
|
|
3
|
+
status: 'ok' | 'broken' | 'redirect' | 'timeout' | 'error' | 'blocked';
|
|
4
4
|
statusCode?: number;
|
|
5
5
|
redirectTarget?: string;
|
|
6
6
|
responseTime?: number;
|
|
@@ -8,15 +8,35 @@ export interface LinkHealthResult {
|
|
|
8
8
|
}
|
|
9
9
|
export interface RedirectChain {
|
|
10
10
|
initialUrl: string;
|
|
11
|
+
/** Whether this is a terminating multi-hop chain or a cyclic redirect loop. */
|
|
12
|
+
kind: 'chain' | 'loop';
|
|
11
13
|
chain: string[];
|
|
12
14
|
finalUrl: string;
|
|
13
15
|
length: number;
|
|
14
16
|
}
|
|
15
|
-
/**
|
|
17
|
+
/** Hard cap on the number of unique links checked per scan (DoS / fan-out guard). */
|
|
18
|
+
export declare const MAX_LINKS = 200;
|
|
19
|
+
/**
|
|
20
|
+
* Scans HTML content for links and checks their health.
|
|
21
|
+
*
|
|
22
|
+
* Outbound requests go through cms-core's `safeFetch` (DNS-resolving SSRF
|
|
23
|
+
* preflight + `redirect: 'manual'`) so a link to an internal/loopback/metadata
|
|
24
|
+
* address can't be used to probe the host. Scans are capped at {@link MAX_LINKS}
|
|
25
|
+
* unique URLs and run with bounded concurrency, each under a hard timeout.
|
|
26
|
+
*/
|
|
16
27
|
export declare function detectBrokenLinks(content: string, baseUrl: string): Promise<LinkHealthResult[]>;
|
|
17
28
|
/** Finds pages that are not linked from any other page. */
|
|
18
29
|
export declare function detectOrphanPages(allPages: string[], linkedPages: string[]): string[];
|
|
19
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Detects multi-hop redirect chains and cyclic redirect loops.
|
|
32
|
+
*
|
|
33
|
+
* A terminating sequence of 2+ redirects (3+ nodes) is a `chain`. A sequence
|
|
34
|
+
* that revisits an earlier node is a `loop` — reported separately because loops
|
|
35
|
+
* cause infinite-redirect crawl errors, whereas chains merely waste crawl
|
|
36
|
+
* budget. Mirrors cms-core's `detectChainsAndLoops`: each loop is reported once
|
|
37
|
+
* (all its members are marked handled) and sub-chains are collapsed into the
|
|
38
|
+
* longest chain from their entry point.
|
|
39
|
+
*/
|
|
20
40
|
export declare function detectRedirectChains(redirects: Array<{
|
|
21
41
|
from: string;
|
|
22
42
|
to: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/link-health/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/link-health/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,IAAI,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAA;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;IACtB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf;AAID,qFAAqF;AACrF,eAAO,MAAM,SAAS,MAAM,CAAA;AA2B5B;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAuD7B;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAGrF;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7C,aAAa,EAAE,CAiDjB"}
|
|
@@ -1,9 +1,37 @@
|
|
|
1
|
+
import { safeFetch, SsrfBlockedError } from '@actuate-media/cms-core';
|
|
1
2
|
const LINK_REGEX = /href=["']([^"']+)["']/gi;
|
|
2
|
-
/**
|
|
3
|
+
/** Hard cap on the number of unique links checked per scan (DoS / fan-out guard). */
|
|
4
|
+
export const MAX_LINKS = 200;
|
|
5
|
+
/** Number of link checks issued in parallel. */
|
|
6
|
+
const CONCURRENCY = 6;
|
|
7
|
+
/** Per-request timeout (ms). */
|
|
8
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
9
|
+
/** Runs `worker` over `items` with a bounded concurrency, preserving input order. */
|
|
10
|
+
async function mapWithConcurrency(items, concurrency, worker) {
|
|
11
|
+
const results = new Array(items.length);
|
|
12
|
+
let cursor = 0;
|
|
13
|
+
async function run() {
|
|
14
|
+
while (cursor < items.length) {
|
|
15
|
+
const index = cursor++;
|
|
16
|
+
results[index] = await worker(items[index], index);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const runners = Array.from({ length: Math.min(concurrency, items.length) }, () => run());
|
|
20
|
+
await Promise.all(runners);
|
|
21
|
+
return results;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Scans HTML content for links and checks their health.
|
|
25
|
+
*
|
|
26
|
+
* Outbound requests go through cms-core's `safeFetch` (DNS-resolving SSRF
|
|
27
|
+
* preflight + `redirect: 'manual'`) so a link to an internal/loopback/metadata
|
|
28
|
+
* address can't be used to probe the host. Scans are capped at {@link MAX_LINKS}
|
|
29
|
+
* unique URLs and run with bounded concurrency, each under a hard timeout.
|
|
30
|
+
*/
|
|
3
31
|
export async function detectBrokenLinks(content, baseUrl) {
|
|
4
32
|
const base = baseUrl.replace(/\/$/, '');
|
|
5
|
-
const results = [];
|
|
6
33
|
const seen = new Set();
|
|
34
|
+
const targets = [];
|
|
7
35
|
let match;
|
|
8
36
|
while ((match = LINK_REGEX.exec(content)) !== null) {
|
|
9
37
|
const href = match[1];
|
|
@@ -14,63 +42,99 @@ export async function detectBrokenLinks(content, baseUrl) {
|
|
|
14
42
|
if (seen.has(url))
|
|
15
43
|
continue;
|
|
16
44
|
seen.add(url);
|
|
45
|
+
targets.push({ url, source: href });
|
|
46
|
+
if (targets.length >= MAX_LINKS)
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
return mapWithConcurrency(targets, CONCURRENCY, async ({ url, source }) => {
|
|
50
|
+
const started = Date.now();
|
|
17
51
|
try {
|
|
18
|
-
const
|
|
19
|
-
const timeout = setTimeout(() => controller.abort(), 10_000);
|
|
20
|
-
const response = await fetch(url, {
|
|
52
|
+
const response = await safeFetch(url, {
|
|
21
53
|
method: 'HEAD',
|
|
22
|
-
|
|
23
|
-
|
|
54
|
+
timeoutMs: REQUEST_TIMEOUT_MS,
|
|
55
|
+
requireDnsCheck: true,
|
|
24
56
|
});
|
|
25
|
-
|
|
57
|
+
const responseTime = Date.now() - started;
|
|
26
58
|
if (response.status >= 300 && response.status < 400) {
|
|
27
|
-
|
|
59
|
+
return {
|
|
28
60
|
url,
|
|
29
61
|
status: 'redirect',
|
|
30
62
|
statusCode: response.status,
|
|
31
63
|
redirectTarget: response.headers.get('location') ?? undefined,
|
|
32
|
-
|
|
33
|
-
|
|
64
|
+
responseTime,
|
|
65
|
+
source,
|
|
66
|
+
};
|
|
34
67
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
results.push({ url, status: 'broken', statusCode: response.status, source: href });
|
|
68
|
+
if (response.ok) {
|
|
69
|
+
return { url, status: 'ok', statusCode: response.status, responseTime, source };
|
|
40
70
|
}
|
|
71
|
+
return { url, status: 'broken', statusCode: response.status, responseTime, source };
|
|
41
72
|
}
|
|
42
73
|
catch (error) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
url,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
74
|
+
const responseTime = Date.now() - started;
|
|
75
|
+
if (error instanceof SsrfBlockedError) {
|
|
76
|
+
return { url, status: 'blocked', responseTime, source };
|
|
77
|
+
}
|
|
78
|
+
const isTimeout = error instanceof DOMException &&
|
|
79
|
+
(error.name === 'TimeoutError' || error.name === 'AbortError');
|
|
80
|
+
return { url, status: isTimeout ? 'timeout' : 'error', responseTime, source };
|
|
49
81
|
}
|
|
50
|
-
}
|
|
51
|
-
return results;
|
|
82
|
+
});
|
|
52
83
|
}
|
|
53
84
|
/** Finds pages that are not linked from any other page. */
|
|
54
85
|
export function detectOrphanPages(allPages, linkedPages) {
|
|
55
86
|
const linkedSet = new Set(linkedPages.map((p) => p.replace(/\/$/, '').toLowerCase()));
|
|
56
87
|
return allPages.filter((page) => !linkedSet.has(page.replace(/\/$/, '').toLowerCase()));
|
|
57
88
|
}
|
|
58
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* Detects multi-hop redirect chains and cyclic redirect loops.
|
|
91
|
+
*
|
|
92
|
+
* A terminating sequence of 2+ redirects (3+ nodes) is a `chain`. A sequence
|
|
93
|
+
* that revisits an earlier node is a `loop` — reported separately because loops
|
|
94
|
+
* cause infinite-redirect crawl errors, whereas chains merely waste crawl
|
|
95
|
+
* budget. Mirrors cms-core's `detectChainsAndLoops`: each loop is reported once
|
|
96
|
+
* (all its members are marked handled) and sub-chains are collapsed into the
|
|
97
|
+
* longest chain from their entry point.
|
|
98
|
+
*/
|
|
59
99
|
export function detectRedirectChains(redirects) {
|
|
60
100
|
const redirectMap = new Map(redirects.map((r) => [r.from, r.to]));
|
|
61
101
|
const chains = [];
|
|
102
|
+
const reported = new Set();
|
|
62
103
|
for (const { from } of redirects) {
|
|
104
|
+
if (reported.has(from))
|
|
105
|
+
continue;
|
|
63
106
|
const chain = [from];
|
|
107
|
+
const visited = new Set([from]);
|
|
64
108
|
let current = from;
|
|
65
|
-
|
|
66
|
-
while (redirectMap.has(current)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
109
|
+
let loop = false;
|
|
110
|
+
while (redirectMap.has(current)) {
|
|
111
|
+
const next = redirectMap.get(current);
|
|
112
|
+
chain.push(next);
|
|
113
|
+
if (visited.has(next)) {
|
|
114
|
+
loop = true;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
visited.add(next);
|
|
118
|
+
current = next;
|
|
119
|
+
}
|
|
120
|
+
if (loop) {
|
|
121
|
+
// Report each cycle once; mark every member handled.
|
|
122
|
+
chain.forEach((node) => reported.add(node));
|
|
123
|
+
chains.push({
|
|
124
|
+
initialUrl: from,
|
|
125
|
+
kind: 'loop',
|
|
126
|
+
chain,
|
|
127
|
+
finalUrl: chain[chain.length - 1] ?? '',
|
|
128
|
+
length: chain.length - 1,
|
|
129
|
+
});
|
|
70
130
|
}
|
|
71
|
-
if (chain.length > 2) {
|
|
131
|
+
else if (chain.length > 2) {
|
|
132
|
+
// Collapse sub-chains: mark every non-terminal node handled so we don't
|
|
133
|
+
// re-emit the tail of this chain from a later starting point.
|
|
134
|
+
chain.slice(0, -1).forEach((node) => reported.add(node));
|
|
72
135
|
chains.push({
|
|
73
136
|
initialUrl: from,
|
|
137
|
+
kind: 'chain',
|
|
74
138
|
chain,
|
|
75
139
|
finalUrl: chain[chain.length - 1] ?? '',
|
|
76
140
|
length: chain.length - 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/link-health/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/link-health/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/robots/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/robots/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,SAAS,EAAE,MAAM,CAAA;QACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;QACnB,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAC,CAAA;IACF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5B;AAUD,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAuC9D"}
|
package/dist/robots/index.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
'Google-Extended',
|
|
10
|
-
];
|
|
1
|
+
import { AI_TRAINING_BOTS, AI_RETRIEVAL_BOTS } from '@actuate-media/cms-core';
|
|
2
|
+
/**
|
|
3
|
+
* Canonical AI-crawler blocklist. Delegates to cms-core's curated taxonomy
|
|
4
|
+
* (AI_TRAINING_BOTS + AI_RETRIEVAL_BOTS) so the plugin and the core /robots.txt
|
|
5
|
+
* route share a single source of truth instead of drifting apart. The legacy
|
|
6
|
+
* `blockAIBots` boolean blocks both groups, matching core's behavior.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_AI_BOTS = [...AI_TRAINING_BOTS, ...AI_RETRIEVAL_BOTS];
|
|
11
9
|
/** Generates a robots.txt string from the given configuration. */
|
|
12
10
|
export function generateRobotsTxt(config) {
|
|
13
11
|
const lines = [];
|
|
@@ -30,7 +28,8 @@ export function generateRobotsTxt(config) {
|
|
|
30
28
|
lines.push('');
|
|
31
29
|
}
|
|
32
30
|
if (config.blockAIBots) {
|
|
33
|
-
|
|
31
|
+
// Dedupe in case an integrator repeats a canonical token in additionalAIBots.
|
|
32
|
+
const bots = [...new Set([...DEFAULT_AI_BOTS, ...(config.additionalAIBots ?? [])])];
|
|
34
33
|
for (const bot of bots) {
|
|
35
34
|
lines.push(`User-agent: ${bot}`);
|
|
36
35
|
lines.push('Disallow: /');
|
package/dist/robots/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/robots/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/robots/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAc7E;;;;;GAKG;AACH,MAAM,eAAe,GAAsB,CAAC,GAAG,gBAAgB,EAAE,GAAG,iBAAiB,CAAC,CAAA;AAEtF,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;IAE/F,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;QAC3C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAA;YACjC,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;QAC/C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChB,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,8EAA8E;QAC9E,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACnF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC,CAAA;YAChC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,UAAU,EAAE,CAAC,CAAA;QAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
import { type ValidationResult } from './validator.js';
|
|
1
2
|
/** Builds a nested JSON-LD structure with @context, @type, and related entities. */
|
|
2
3
|
export declare function composeSchema(type: string, data: Record<string, unknown>, nested?: Record<string, unknown>): Record<string, unknown>;
|
|
4
|
+
/**
|
|
5
|
+
* Composes a JSON-LD node and validates it against Schema.org requirements in
|
|
6
|
+
* one step — the compose path that actually exercises the validator so nodes
|
|
7
|
+
* missing required fields (invalid Review/Event/JobPosting, etc.) are flagged
|
|
8
|
+
* instead of shipping silently. Returns the composed `schema` alongside its
|
|
9
|
+
* `validation` result; callers (e.g. the SEO audit UI) surface the warnings.
|
|
10
|
+
*/
|
|
11
|
+
export declare function composeAndValidateSchema(type: string, data: Record<string, unknown>, nested?: Record<string, unknown>): {
|
|
12
|
+
schema: Record<string, unknown>;
|
|
13
|
+
validation: ValidationResult;
|
|
14
|
+
};
|
|
3
15
|
//# sourceMappingURL=composer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../src/schema/composer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../src/schema/composer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAwB3E,oFAAoF;AACpF,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2CzB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,UAAU,EAAE,gBAAgB,CAAA;CAAE,CAGnE"}
|
package/dist/schema/composer.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateSchemaGraph } from './validator.js';
|
|
1
2
|
const NESTED_ENTITY_MAP = {
|
|
2
3
|
Article: [
|
|
3
4
|
{ field: 'author', type: 'Person' },
|
|
@@ -63,4 +64,15 @@ export function composeSchema(type, data, nested) {
|
|
|
63
64
|
}
|
|
64
65
|
return schema;
|
|
65
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Composes a JSON-LD node and validates it against Schema.org requirements in
|
|
69
|
+
* one step — the compose path that actually exercises the validator so nodes
|
|
70
|
+
* missing required fields (invalid Review/Event/JobPosting, etc.) are flagged
|
|
71
|
+
* instead of shipping silently. Returns the composed `schema` alongside its
|
|
72
|
+
* `validation` result; callers (e.g. the SEO audit UI) surface the warnings.
|
|
73
|
+
*/
|
|
74
|
+
export function composeAndValidateSchema(type, data, nested) {
|
|
75
|
+
const schema = composeSchema(type, data, nested);
|
|
76
|
+
return { schema, validation: validateSchemaGraph(schema) };
|
|
77
|
+
}
|
|
66
78
|
//# sourceMappingURL=composer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer.js","sourceRoot":"","sources":["../../src/schema/composer.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAA2D;IAChF,OAAO,EAAE;QACP,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;QACnC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,EAAE;KAC7C;IACD,KAAK,EAAE;QACL,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,EAAE;QAC5C,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE;KACrC;IACD,UAAU,EAAE;QACV,EAAE,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,cAAc,EAAE;QACrD,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE;KACxC;IACD,MAAM,EAAE;QACN,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;QACnC,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE;KACzC;IACD,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IACnD,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IACtD,aAAa,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;CAC7D,CAAA;AAED,oFAAoF;AACpF,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,IAA6B,EAC7B,MAAgC;IAEhC,MAAM,MAAM,GAA4B;QACtC,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,IAAI;KACd,CAAA;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAQ;QACjC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAC1D,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACrB,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAChD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAwC,CAAA;QAC7E,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG;gBAClB,OAAO,EAAE,GAAG,CAAC,IAAI;gBACjB,GAAG,UAAU;aACd,CAAA;QACH,CAAC;aAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC;YACxF,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG;gBAClB,OAAO,EAAE,GAAG,CAAC,IAAI;gBACjB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;aACtB,CAAA;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC;gBAAE,SAAQ;YACrD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChE,MAAM,SAAS,GAAG,KAAgC,CAAA;gBAClD,MAAM,CAAC,GAAG,CAAC,GAAG;oBACZ,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO;oBACtC,GAAG,SAAS;iBACb,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
1
|
+
{"version":3,"file":"composer.js","sourceRoot":"","sources":["../../src/schema/composer.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,4 +8,16 @@ export interface ValidationResult {
|
|
|
8
8
|
}
|
|
9
9
|
/** Validates a JSON-LD schema object against Schema.org requirements. */
|
|
10
10
|
export declare function validateSchema(schema: Record<string, unknown>): ValidationResult;
|
|
11
|
+
/**
|
|
12
|
+
* Validates emitted JSON-LD that may be a single node, an array of nodes, or a
|
|
13
|
+
* `@graph` wrapper (`{ '@context', '@graph': [...] }`) — the shape the compose
|
|
14
|
+
* path produces. Each node is checked with {@link validateSchema} and its field
|
|
15
|
+
* paths are prefixed with the node's position so a caller can pinpoint which
|
|
16
|
+
* node in the graph is missing a required field.
|
|
17
|
+
*
|
|
18
|
+
* This is the safety net that connects the validator to the compose path: nodes
|
|
19
|
+
* missing required fields are surfaced as errors instead of silently shipping
|
|
20
|
+
* invalid structured data.
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateSchemaGraph(input: Record<string, unknown> | Array<Record<string, unknown>>): ValidationResult;
|
|
11
23
|
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/schema/validator.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;KAC9B,CAAC,CAAA;CACH;AA8BD,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAqFhF"}
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/schema/validator.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;KAC9B,CAAC,CAAA;CACH;AA8BD,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAqFhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC9D,gBAAgB,CAgClB"}
|
package/dist/schema/validator.js
CHANGED
|
@@ -104,4 +104,45 @@ export function validateSchema(schema) {
|
|
|
104
104
|
const hasErrors = errors.some((e) => e.severity === 'error');
|
|
105
105
|
return { valid: !hasErrors, errors };
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Validates emitted JSON-LD that may be a single node, an array of nodes, or a
|
|
109
|
+
* `@graph` wrapper (`{ '@context', '@graph': [...] }`) — the shape the compose
|
|
110
|
+
* path produces. Each node is checked with {@link validateSchema} and its field
|
|
111
|
+
* paths are prefixed with the node's position so a caller can pinpoint which
|
|
112
|
+
* node in the graph is missing a required field.
|
|
113
|
+
*
|
|
114
|
+
* This is the safety net that connects the validator to the compose path: nodes
|
|
115
|
+
* missing required fields are surfaced as errors instead of silently shipping
|
|
116
|
+
* invalid structured data.
|
|
117
|
+
*/
|
|
118
|
+
export function validateSchemaGraph(input) {
|
|
119
|
+
let graph;
|
|
120
|
+
let context;
|
|
121
|
+
if (Array.isArray(input)) {
|
|
122
|
+
graph = input;
|
|
123
|
+
context = undefined;
|
|
124
|
+
}
|
|
125
|
+
else if (Array.isArray(input['@graph'])) {
|
|
126
|
+
graph = input['@graph'];
|
|
127
|
+
context = input['@context'];
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// Not a graph/array — validate the single node directly.
|
|
131
|
+
return validateSchema(input);
|
|
132
|
+
}
|
|
133
|
+
const errors = [];
|
|
134
|
+
graph.forEach((node, i) => {
|
|
135
|
+
// A `@graph` shares a single top-level `@context`; don't flag every node for
|
|
136
|
+
// a missing `@context` when the wrapper provides one.
|
|
137
|
+
const nodeForCheck = context !== undefined && node['@context'] === undefined
|
|
138
|
+
? { ...node, '@context': context }
|
|
139
|
+
: node;
|
|
140
|
+
const result = validateSchema(nodeForCheck);
|
|
141
|
+
for (const err of result.errors) {
|
|
142
|
+
errors.push({ ...err, field: `@graph[${i}].${err.field}` });
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const hasErrors = errors.some((e) => e.severity === 'error');
|
|
146
|
+
return { valid: !hasErrors, errors };
|
|
147
|
+
}
|
|
107
148
|
//# sourceMappingURL=validator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/schema/validator.ts"],"names":[],"mappings":"AASA,MAAM,eAAe,GAA6B;IAChD,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,CAAC;IAChD,OAAO,EAAE,CAAC,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,MAAM,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,CAAC;IACtB,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;IAC5B,OAAO,EAAE,CAAC,YAAY,CAAC;IACvB,OAAO,EAAE,CAAC,MAAM,CAAC;IACjB,UAAU,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,oBAAoB,CAAC;IACzD,aAAa,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;IAClC,MAAM,EAAE,CAAC,cAAc,EAAE,QAAQ,EAAE,cAAc,CAAC;IAClD,OAAO,EAAE,CAAC,MAAM,CAAC;CAClB,CAAA;AAED,MAAM,kBAAkB,GAA6B;IACnD,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,CAAC;IAC9D,OAAO,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC;IAC/B,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,YAAY,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;IAC7B,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC;IACtD,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC;IACpC,UAAU,EAAE,CAAC,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,cAAc,CAAC;IAC3E,aAAa,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,KAAK,CAAC;IACnD,MAAM,EAAE,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,OAAO,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,CAAC;CACrD,CAAA;AAED,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,MAA+B;IAC5D,MAAM,MAAM,GAA+B,EAAE,CAAA;IAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAuB,CAAA;IAElD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,UAAU;YACjB,OAAO,EAAE,mDAAmD;YAC5D,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,yDAAyD;YAClE,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAA;QACF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;IACjC,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAC5C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK;gBACL,OAAO,EAAE,mBAAmB,KAAK,yBAAyB,IAAI,EAAE;gBAChE,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAClD,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK;gBACL,OAAO,EAAE,sBAAsB,KAAK,yBAAyB,IAAI,EAAE;gBACnE,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;QACnC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,UAAU;gBACjB,OAAO,EAAE,sEAAsE;gBAC/E,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAmC,CAAA;QACxE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAE,CAAA;YACvB,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,UAAU,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC;oBACV,KAAK,EAAE,cAAc,CAAC,SAAS;oBAC/B,OAAO,EAAE,sCAAsC;oBAC/C,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAA;YACJ,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC;oBACV,KAAK,EAAE,cAAc,CAAC,QAAQ;oBAC9B,OAAO,EAAE,8DAA8D;oBACvE,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAA;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,CAAC,gBAAgB,CAAwC,CAAA;YACzE,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC;oBACV,KAAK,EAAE,cAAc,CAAC,uBAAuB;oBAC7C,OAAO,EAAE,wCAAwC;oBACjD,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAA;IAC5D,OAAO,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,CAAA;AACtC,CAAC"}
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/schema/validator.ts"],"names":[],"mappings":"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"}
|
package/dist/sitemap/index.d.ts
CHANGED
|
@@ -4,6 +4,14 @@ export interface SitemapEntry {
|
|
|
4
4
|
changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
|
|
5
5
|
priority?: number;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Google rejects a sitemap file with more than 50,000 URLs or larger than 50 MB
|
|
9
|
+
* uncompressed. `generateCollectionSitemap` enforces both — a consumer feeding
|
|
10
|
+
* it an entire collection must paginate upstream (mirrors the core route, which
|
|
11
|
+
* splits at SITEMAP_PAGE_SIZE) rather than emit an oversized file Google drops.
|
|
12
|
+
*/
|
|
13
|
+
export declare const SITEMAP_MAX_URLS = 50000;
|
|
14
|
+
export declare const SITEMAP_MAX_BYTES: number;
|
|
7
15
|
export interface ImageSitemapEntry {
|
|
8
16
|
pageUrl: string;
|
|
9
17
|
images: Array<{
|
|
@@ -52,6 +60,13 @@ export interface CollectionSitemapConfig {
|
|
|
52
60
|
sitemapChangeFreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
|
|
53
61
|
excludeFromSitemap?: boolean;
|
|
54
62
|
archivePath?: string;
|
|
63
|
+
/**
|
|
64
|
+
* The newest child entry's last-modified timestamp (ISO 8601). Used as the
|
|
65
|
+
* `<lastmod>` for this collection in the sitemap index. Prefer an accurate
|
|
66
|
+
* value from the collection's most-recently-updated document — a lastmod that
|
|
67
|
+
* changes on every fetch trains crawlers to ignore the signal.
|
|
68
|
+
*/
|
|
69
|
+
lastmod?: string;
|
|
55
70
|
}
|
|
56
71
|
/**
|
|
57
72
|
* Build the public URL for a document given its collection config and slug.
|
|
@@ -59,7 +74,15 @@ export interface CollectionSitemapConfig {
|
|
|
59
74
|
* - Posts (urlPrefix: "blog") -> `{baseUrl}/blog/{slug}`
|
|
60
75
|
*/
|
|
61
76
|
export declare function buildDocumentUrl(baseUrl: string, urlPrefix: string | undefined, slug: string): string;
|
|
62
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Generates a sitemap index XML referencing per-collection sitemaps.
|
|
79
|
+
*
|
|
80
|
+
* Child URLs follow the same Yoast-style naming the core route serves
|
|
81
|
+
* (`{base}/{name}-sitemap.xml`). `<lastmod>` is derived from each collection's
|
|
82
|
+
* newest child entry (`CollectionSitemapConfig.lastmod`) and omitted when
|
|
83
|
+
* unknown — never stamped with `Date.now()`, which would churn on every fetch
|
|
84
|
+
* and train crawlers to ignore lastmod entirely.
|
|
85
|
+
*/
|
|
63
86
|
export declare function generateSitemapIndex(collections: (string | CollectionSitemapConfig)[], baseUrl: string): string;
|
|
64
87
|
/**
|
|
65
88
|
* Generates a sitemap XML for a collection's documents.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sitemap/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sitemap/index.ts"],"names":[],"mappings":"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"}
|
package/dist/sitemap/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { sitemapBaseName, collectionSitemapFilename } from '@actuate-media/cms-core';
|
|
2
|
+
/**
|
|
3
|
+
* Google rejects a sitemap file with more than 50,000 URLs or larger than 50 MB
|
|
4
|
+
* uncompressed. `generateCollectionSitemap` enforces both — a consumer feeding
|
|
5
|
+
* it an entire collection must paginate upstream (mirrors the core route, which
|
|
6
|
+
* splits at SITEMAP_PAGE_SIZE) rather than emit an oversized file Google drops.
|
|
7
|
+
*/
|
|
8
|
+
export const SITEMAP_MAX_URLS = 50_000;
|
|
9
|
+
export const SITEMAP_MAX_BYTES = 50 * 1024 * 1024;
|
|
1
10
|
function xmlEscape(str) {
|
|
2
11
|
return str
|
|
3
12
|
.replace(/&/g, '&')
|
|
@@ -19,7 +28,15 @@ export function buildDocumentUrl(baseUrl, urlPrefix, slug) {
|
|
|
19
28
|
}
|
|
20
29
|
return `${base}/${slug}`;
|
|
21
30
|
}
|
|
22
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Generates a sitemap index XML referencing per-collection sitemaps.
|
|
33
|
+
*
|
|
34
|
+
* Child URLs follow the same Yoast-style naming the core route serves
|
|
35
|
+
* (`{base}/{name}-sitemap.xml`). `<lastmod>` is derived from each collection's
|
|
36
|
+
* newest child entry (`CollectionSitemapConfig.lastmod`) and omitted when
|
|
37
|
+
* unknown — never stamped with `Date.now()`, which would churn on every fetch
|
|
38
|
+
* and train crawlers to ignore lastmod entirely.
|
|
39
|
+
*/
|
|
23
40
|
export function generateSitemapIndex(collections, baseUrl) {
|
|
24
41
|
const base = baseUrl.replace(/\/$/, '');
|
|
25
42
|
const sitemaps = collections
|
|
@@ -29,8 +46,14 @@ export function generateSitemapIndex(collections, baseUrl) {
|
|
|
29
46
|
return !col.excludeFromSitemap;
|
|
30
47
|
})
|
|
31
48
|
.map((col) => {
|
|
32
|
-
const
|
|
33
|
-
|
|
49
|
+
const cfg = typeof col === 'string' ? { slug: col } : col;
|
|
50
|
+
const baseName = sitemapBaseName({ slug: cfg.slug, type: cfg.type });
|
|
51
|
+
const loc = `${base}/${collectionSitemapFilename(baseName, 0)}`;
|
|
52
|
+
let xml = ` <sitemap>\n <loc>${xmlEscape(loc)}</loc>`;
|
|
53
|
+
if (cfg.lastmod)
|
|
54
|
+
xml += `\n <lastmod>${xmlEscape(cfg.lastmod)}</lastmod>`;
|
|
55
|
+
xml += '\n </sitemap>';
|
|
56
|
+
return xml;
|
|
34
57
|
})
|
|
35
58
|
.join('\n');
|
|
36
59
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -53,6 +76,10 @@ export function generateCollectionSitemap(entries, baseUrl, collectionConfig) {
|
|
|
53
76
|
priority: 0.6,
|
|
54
77
|
});
|
|
55
78
|
}
|
|
79
|
+
if (allEntries.length > SITEMAP_MAX_URLS) {
|
|
80
|
+
throw new RangeError(`Sitemap would contain ${allEntries.length} URLs, exceeding the ${SITEMAP_MAX_URLS} limit. ` +
|
|
81
|
+
'Paginate the collection into multiple sitemap files.');
|
|
82
|
+
}
|
|
56
83
|
const urls = allEntries
|
|
57
84
|
.map((entry) => {
|
|
58
85
|
let loc;
|
|
@@ -82,10 +109,16 @@ export function generateCollectionSitemap(entries, baseUrl, collectionConfig) {
|
|
|
82
109
|
return xml;
|
|
83
110
|
})
|
|
84
111
|
.join('\n');
|
|
85
|
-
|
|
112
|
+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
86
113
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
87
114
|
${urls}
|
|
88
115
|
</urlset>`;
|
|
116
|
+
const bytes = new TextEncoder().encode(xml).length;
|
|
117
|
+
if (bytes > SITEMAP_MAX_BYTES) {
|
|
118
|
+
throw new RangeError(`Sitemap is ${bytes} bytes, exceeding the ${SITEMAP_MAX_BYTES}-byte (50 MB) limit. ` +
|
|
119
|
+
'Paginate the collection into multiple sitemap files.');
|
|
120
|
+
}
|
|
121
|
+
return xml;
|
|
89
122
|
}
|
|
90
123
|
/** Generates a Google Image sitemap extension. */
|
|
91
124
|
export function generateImageSitemap(entries) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sitemap/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sitemap/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actuate-media/plugin-seo",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@types/react": "^19.0.0",
|
|
29
29
|
"typescript": "^5.7.0",
|
|
30
30
|
"vitest": "^4.1.0",
|
|
31
|
-
"@actuate-media/cms-core": "0.
|
|
31
|
+
"@actuate-media/cms-core": "0.93.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@actuate-media/cms-core": ">=0.1.0",
|