@cogenta/seo 0.2.0 → 0.3.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/dist/content-analysis.d.ts +33 -0
- package/dist/content-analysis.d.ts.map +1 -0
- package/dist/content-analysis.js +141 -0
- package/dist/content-analysis.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/indexable.d.ts +12 -1
- package/dist/indexable.d.ts.map +1 -1
- package/dist/indexable.js +19 -1
- package/dist/indexable.js.map +1 -1
- package/dist/link-assistant.d.ts +51 -0
- package/dist/link-assistant.d.ts.map +1 -0
- package/dist/link-assistant.js +80 -0
- package/dist/link-assistant.js.map +1 -0
- package/dist/metadata.d.ts +19 -1
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +83 -8
- package/dist/metadata.js.map +1 -1
- package/dist/robots.d.ts +20 -0
- package/dist/robots.d.ts.map +1 -1
- package/dist/robots.js +19 -0
- package/dist/robots.js.map +1 -1
- package/dist/search-console.d.ts +66 -0
- package/dist/search-console.d.ts.map +1 -0
- package/dist/search-console.js +169 -0
- package/dist/search-console.js.map +1 -0
- package/dist/sitemap.d.ts +15 -0
- package/dist/sitemap.d.ts.map +1 -1
- package/dist/sitemap.js +6 -0
- package/dist/sitemap.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { queryTokens } from '@cogenta/schema';
|
|
2
|
+
export type ContentCheckId = 'keywordInTitle' | 'keywordInDescription' | 'keywordInFirstSentence' | 'keywordDensity' | 'sentenceLength' | 'subheadings' | 'contentLength';
|
|
3
|
+
export interface ContentCheck {
|
|
4
|
+
readonly id: ContentCheckId;
|
|
5
|
+
readonly passed: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* A number a caller may want to render next to the check
|
|
8
|
+
* (`keywordDensity`'s percentage, `sentenceLength`'s longest sentence word
|
|
9
|
+
* count, `contentLength`'s word count) — never itself the score, and never
|
|
10
|
+
* shown with false precision by this file (a caller renders it as an
|
|
11
|
+
* integer, not a decimal).
|
|
12
|
+
*/
|
|
13
|
+
readonly detail?: number;
|
|
14
|
+
}
|
|
15
|
+
export type ContentScoreLevel = 'red' | 'orange' | 'green';
|
|
16
|
+
export interface ContentAnalysisInput {
|
|
17
|
+
readonly title: string;
|
|
18
|
+
readonly description?: string;
|
|
19
|
+
/** Empty/absent skips the four keyword-dependent checks — see this file's own module comment. */
|
|
20
|
+
readonly focusKeyword?: string;
|
|
21
|
+
/** A contract-A rich text document (`RichTextDocument`-shaped), or anything else — parsed defensively, like `extractRichText`. */
|
|
22
|
+
readonly body: unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface ContentAnalysisResult {
|
|
25
|
+
readonly checks: readonly ContentCheck[];
|
|
26
|
+
readonly score: ContentScoreLevel;
|
|
27
|
+
readonly passedCount: number;
|
|
28
|
+
readonly totalCount: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function analyseContent(input: ContentAnalysisInput): ContentAnalysisResult;
|
|
31
|
+
/** `queryTokens` re-exported for callers that want the same word-matching Cogenta's search already uses on top of a raw analysis result — not used internally by `analyseContent` itself, kept here only so a consumer never has to add its own `@cogenta/schema` dependency just to tokenize a suggestion. */
|
|
32
|
+
export { queryTokens };
|
|
33
|
+
//# sourceMappingURL=content-analysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-analysis.d.ts","sourceRoot":"","sources":["../src/content-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAiJjE,MAAM,MAAM,cAAc,GACtB,gBAAgB,GAChB,sBAAsB,GACtB,wBAAwB,GACxB,gBAAgB,GAChB,gBAAgB,GAChB,aAAa,GACb,eAAe,CAAA;AAEnB,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE1D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,iGAAiG;IACjG,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,kIAAkI;IAClI,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAUD,wBAAgB,cAAc,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CA0DjF;AAED,+SAA+S;AAC/S,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { condense, foldText, queryTokens } from '@cogenta/schema';
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
/** Contract A's `RICH_TEXT_STYLES` minus `'normal'`/`'blockquote'` — the two that read as a subheading in an outline. Duplicated rather than imported from `@cogenta/schema`'s `rich-text.ts` (`RICH_TEXT_STYLES`): importing three literals is not worth a dependency edge this file does not otherwise need, the same call `seo.tsx`'s own `ROBOTS_DISALLOW_ALL_PATTERN` comment makes for a one-regex duplication. */
|
|
6
|
+
const HEADING_STYLES = new Set(['h2', 'h3', 'h4']);
|
|
7
|
+
function textOf(node) {
|
|
8
|
+
const children = node.children;
|
|
9
|
+
if (!Array.isArray(children))
|
|
10
|
+
return '';
|
|
11
|
+
const parts = [];
|
|
12
|
+
for (const child of children) {
|
|
13
|
+
if (!isRecord(child))
|
|
14
|
+
continue;
|
|
15
|
+
const span = child;
|
|
16
|
+
if (typeof span.text === 'string')
|
|
17
|
+
parts.push(span.text);
|
|
18
|
+
}
|
|
19
|
+
return parts.join('');
|
|
20
|
+
}
|
|
21
|
+
/** Defensively `unknown`, like `extractRichText` — an entry mid-edit in the admin can hold anything the editor has not saved yet. */
|
|
22
|
+
function parseBody(body) {
|
|
23
|
+
if (!Array.isArray(body))
|
|
24
|
+
return { blocks: [], headingCount: 0 };
|
|
25
|
+
const blocks = [];
|
|
26
|
+
let headingCount = 0;
|
|
27
|
+
for (const node of body) {
|
|
28
|
+
if (!isRecord(node) || node._type !== 'block')
|
|
29
|
+
continue;
|
|
30
|
+
const block = node;
|
|
31
|
+
const text = condense(textOf(block));
|
|
32
|
+
if (text.length === 0)
|
|
33
|
+
continue;
|
|
34
|
+
const heading = typeof block.style === 'string' && HEADING_STYLES.has(block.style);
|
|
35
|
+
blocks.push({ text, heading });
|
|
36
|
+
if (heading)
|
|
37
|
+
headingCount += 1;
|
|
38
|
+
}
|
|
39
|
+
return { blocks, headingCount };
|
|
40
|
+
}
|
|
41
|
+
/** Words per sentence beyond which a sentence is flagged — Yoast's own published readability threshold (20 words), the closest thing this space has to an industry convention. */
|
|
42
|
+
const MAX_SENTENCE_WORDS = 20;
|
|
43
|
+
/** Below this, an article is short enough that going without a subheading is not itself a problem — `subheadings` is skipped rather than failed. */
|
|
44
|
+
const SHORT_CONTENT_WORDS = 300;
|
|
45
|
+
/** The minimum word count `contentLength` asks for — the same 300-word floor most of these tools converge on for "a real article", not a Cogenta invention. */
|
|
46
|
+
const MIN_CONTENT_WORDS = 300;
|
|
47
|
+
/** Keyword density band `keywordDensity` passes within, expressed as a percentage of total words — TruSEO's own published target range. Below it reads as "barely used"; above it reads as stuffing. */
|
|
48
|
+
const MIN_KEYWORD_DENSITY = 0.5;
|
|
49
|
+
const MAX_KEYWORD_DENSITY = 2.5;
|
|
50
|
+
const SENTENCE_SPLIT_PATTERN = /[^.!?]+[.!?]*/gu;
|
|
51
|
+
function sentencesOf(text) {
|
|
52
|
+
return (text.match(SENTENCE_SPLIT_PATTERN) ?? [])
|
|
53
|
+
.map((sentence) => sentence.trim())
|
|
54
|
+
.filter((sentence) => sentence.length > 0);
|
|
55
|
+
}
|
|
56
|
+
function wordCountOf(text) {
|
|
57
|
+
return text.trim() === '' ? 0 : text.trim().split(/\s+/u).length;
|
|
58
|
+
}
|
|
59
|
+
/** First sentence of the first *prose* block — a heading is not a sentence, so it is skipped in favour of the first `'normal'`/`'blockquote'` block, falling back to the very first block at all when the body is nothing but headings. */
|
|
60
|
+
function firstSentenceOf(blocks) {
|
|
61
|
+
const first = blocks.find((block) => !block.heading) ?? blocks[0];
|
|
62
|
+
if (first === undefined)
|
|
63
|
+
return '';
|
|
64
|
+
const sentences = sentencesOf(first.text);
|
|
65
|
+
return sentences[0] ?? first.text;
|
|
66
|
+
}
|
|
67
|
+
/** How many times `needle` occurs in `haystack`, both already folded — a plain substring count, not a word-boundary regex, so a multi-word keyword phrase ("guide de voyage") is counted as one unit exactly as `foldText`/`queryTokens` already treat phrases in `@cogenta/schema`'s own search layer. */
|
|
68
|
+
function occurrencesOf(haystack, needle) {
|
|
69
|
+
if (needle === '')
|
|
70
|
+
return 0;
|
|
71
|
+
let count = 0;
|
|
72
|
+
let index = haystack.indexOf(needle);
|
|
73
|
+
while (index !== -1) {
|
|
74
|
+
count += 1;
|
|
75
|
+
index = haystack.indexOf(needle, index + needle.length);
|
|
76
|
+
}
|
|
77
|
+
return count;
|
|
78
|
+
}
|
|
79
|
+
function scoreFor(passedCount, totalCount) {
|
|
80
|
+
if (totalCount === 0)
|
|
81
|
+
return 'red';
|
|
82
|
+
const ratio = passedCount / totalCount;
|
|
83
|
+
if (ratio >= 0.8)
|
|
84
|
+
return 'green';
|
|
85
|
+
if (ratio >= 0.5)
|
|
86
|
+
return 'orange';
|
|
87
|
+
return 'red';
|
|
88
|
+
}
|
|
89
|
+
export function analyseContent(input) {
|
|
90
|
+
const { blocks, headingCount } = parseBody(input.body);
|
|
91
|
+
const bodyText = condense(blocks.map((block) => block.text).join(' '));
|
|
92
|
+
const wordCount = wordCountOf(bodyText);
|
|
93
|
+
const checks = [];
|
|
94
|
+
const focusKeyword = (input.focusKeyword ?? '').trim();
|
|
95
|
+
if (focusKeyword !== '') {
|
|
96
|
+
const foldedKeyword = foldText(focusKeyword);
|
|
97
|
+
checks.push({
|
|
98
|
+
id: 'keywordInTitle',
|
|
99
|
+
passed: foldText(input.title).includes(foldedKeyword),
|
|
100
|
+
});
|
|
101
|
+
checks.push({
|
|
102
|
+
id: 'keywordInDescription',
|
|
103
|
+
passed: input.description !== undefined && foldText(input.description).includes(foldedKeyword),
|
|
104
|
+
});
|
|
105
|
+
checks.push({
|
|
106
|
+
id: 'keywordInFirstSentence',
|
|
107
|
+
passed: foldText(firstSentenceOf(blocks)).includes(foldedKeyword),
|
|
108
|
+
});
|
|
109
|
+
const foldedBody = foldText(bodyText);
|
|
110
|
+
const occurrences = occurrencesOf(foldedBody, foldedKeyword);
|
|
111
|
+
const density = wordCount === 0 ? 0 : (occurrences / wordCount) * 100;
|
|
112
|
+
checks.push({
|
|
113
|
+
id: 'keywordDensity',
|
|
114
|
+
passed: density >= MIN_KEYWORD_DENSITY && density <= MAX_KEYWORD_DENSITY,
|
|
115
|
+
detail: Math.round(density * 10) / 10,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const sentenceLengths = sentencesOf(bodyText).map(wordCountOf);
|
|
119
|
+
const longestSentence = sentenceLengths.length === 0 ? 0 : Math.max(...sentenceLengths);
|
|
120
|
+
checks.push({
|
|
121
|
+
id: 'sentenceLength',
|
|
122
|
+
passed: longestSentence <= MAX_SENTENCE_WORDS,
|
|
123
|
+
detail: longestSentence,
|
|
124
|
+
});
|
|
125
|
+
checks.push({
|
|
126
|
+
id: 'subheadings',
|
|
127
|
+
passed: wordCount < SHORT_CONTENT_WORDS || headingCount > 0,
|
|
128
|
+
detail: headingCount,
|
|
129
|
+
});
|
|
130
|
+
checks.push({
|
|
131
|
+
id: 'contentLength',
|
|
132
|
+
passed: wordCount >= MIN_CONTENT_WORDS,
|
|
133
|
+
detail: wordCount,
|
|
134
|
+
});
|
|
135
|
+
const passedCount = checks.filter((check) => check.passed).length;
|
|
136
|
+
const totalCount = checks.length;
|
|
137
|
+
return { checks, score: scoreFor(passedCount, totalCount), passedCount, totalCount };
|
|
138
|
+
}
|
|
139
|
+
/** `queryTokens` re-exported for callers that want the same word-matching Cogenta's search already uses on top of a raw analysis result — not used internally by `analyseContent` itself, kept here only so a consumer never has to add its own `@cogenta/schema` dependency just to tokenize a suggestion. */
|
|
140
|
+
export { queryTokens };
|
|
141
|
+
//# sourceMappingURL=content-analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-analysis.js","sourceRoot":"","sources":["../src/content-analysis.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,23 +15,29 @@
|
|
|
15
15
|
* ping, and never touches the database — it is safe inside the render sandbox
|
|
16
16
|
* (rule R5).
|
|
17
17
|
*/
|
|
18
|
+
export type { ContentAnalysisInput, ContentAnalysisResult, ContentCheck, ContentCheckId, ContentScoreLevel, } from './content-analysis.js';
|
|
19
|
+
export { analyseContent } from './content-analysis.js';
|
|
18
20
|
export type { FeedInput, FeedItem, FeedItemsOptions } from './feeds.js';
|
|
19
21
|
export { feedItemsFor, renderAtomFeed, renderRssFeed, toRfc822 } from './feeds.js';
|
|
20
22
|
export type { HreflangAlternate, TranslationFamily } from './hreflang.js';
|
|
21
23
|
export { alternatesFor, buildHreflangMap, groupTranslationFamilies } from './hreflang.js';
|
|
22
24
|
export type { IndexableOptions } from './indexable.js';
|
|
23
|
-
export { indexableResources, isIndexable, isPublished } from './indexable.js';
|
|
25
|
+
export { indexableResources, isIndexable, isPublished, isSeoNoindexed } from './indexable.js';
|
|
24
26
|
export type { IndexNowFetch, IndexNowOptions, IndexNowResult } from './indexnow.js';
|
|
25
27
|
export { INDEXNOW_MAX_URLS, indexNowKeyFile, pingIndexNow } from './indexnow.js';
|
|
26
28
|
export type { JsonLdObject, JsonLdOptions, JsonLdValue } from './json-ld.js';
|
|
27
29
|
export { buildJsonLd, renderJsonLdScript, schemaTypeFor } from './json-ld.js';
|
|
30
|
+
export type { LinkAssistantReport, LinkSuggestion, OrphanEntry } from './link-assistant.js';
|
|
31
|
+
export { analyseInternalLinks } from './link-assistant.js';
|
|
28
32
|
export type { LlmsTxtLink, LlmsTxtOptions, LlmsTxtSection, LlmsTxtSectionsOptions, } from './llms-txt.js';
|
|
29
33
|
export { llmsTxtSectionsFor, renderLlmsTxt } from './llms-txt.js';
|
|
30
34
|
export type { MetadataOptions, MetaTag } from './metadata.js';
|
|
31
35
|
export { buildMetaTags, escapeHtmlAttribute, escapeHtmlText, renderMetaTags, } from './metadata.js';
|
|
32
36
|
export type { RobotsGroup, RobotsOptions } from './robots.js';
|
|
33
|
-
export { renderRobotsTxt } from './robots.js';
|
|
34
|
-
export type {
|
|
37
|
+
export { renderRobotsTxt, robotsRuleDisallowsEverything } from './robots.js';
|
|
38
|
+
export type { SearchAnalyticsQueryOptions, SearchConsoleFetch, SearchConsoleMetricsRow, SearchConsoleOAuthOptions, SearchConsoleTokens, } from './search-console.js';
|
|
39
|
+
export { buildAuthorizationUrl, exchangeAuthorizationCode, fetchSearchAnalytics, refreshAccessToken, } from './search-console.js';
|
|
40
|
+
export type { ChangeFrequency, SitemapCollectionOverride, SitemapFile, SitemapOptions, SitemapUrl, } from './sitemap.js';
|
|
35
41
|
export { buildSitemap, SITEMAP_MAX_BYTES, SITEMAP_MAX_URLS, sitemapUrlsFor, } from './sitemap.js';
|
|
36
42
|
export type { SeoImage, SeoReference, SeoResolvers, SeoResource, SeoSite } from './types.js';
|
|
37
43
|
export { absoluteUrl, canonicalUrl, hasRoute, normaliseBaseUrl, routeParams } from './url.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;;;;;;;;;;;;;;;;GAgBG;AAEH,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAClF,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;AACzF,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAClF,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;AACzF,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC7F,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAChF,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC5E,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC7E,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC3F,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,YAAY,EACV,WAAW,EACX,cAAc,EACd,cAAc,EACd,sBAAsB,GACvB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AACjE,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAA;AAC5E,YAAY,EACV,2BAA2B,EAC3B,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,eAAe,EACf,yBAAyB,EACzB,WAAW,EACX,cAAc,EACd,UAAU,GACX,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,GACf,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAC5F,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC7F,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACzD,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,UAAU,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -15,14 +15,17 @@
|
|
|
15
15
|
* ping, and never touches the database — it is safe inside the render sandbox
|
|
16
16
|
* (rule R5).
|
|
17
17
|
*/
|
|
18
|
+
export { analyseContent } from './content-analysis.js';
|
|
18
19
|
export { feedItemsFor, renderAtomFeed, renderRssFeed, toRfc822 } from './feeds.js';
|
|
19
20
|
export { alternatesFor, buildHreflangMap, groupTranslationFamilies } from './hreflang.js';
|
|
20
|
-
export { indexableResources, isIndexable, isPublished } from './indexable.js';
|
|
21
|
+
export { indexableResources, isIndexable, isPublished, isSeoNoindexed } from './indexable.js';
|
|
21
22
|
export { INDEXNOW_MAX_URLS, indexNowKeyFile, pingIndexNow } from './indexnow.js';
|
|
22
23
|
export { buildJsonLd, renderJsonLdScript, schemaTypeFor } from './json-ld.js';
|
|
24
|
+
export { analyseInternalLinks } from './link-assistant.js';
|
|
23
25
|
export { llmsTxtSectionsFor, renderLlmsTxt } from './llms-txt.js';
|
|
24
26
|
export { buildMetaTags, escapeHtmlAttribute, escapeHtmlText, renderMetaTags, } from './metadata.js';
|
|
25
|
-
export { renderRobotsTxt } from './robots.js';
|
|
27
|
+
export { renderRobotsTxt, robotsRuleDisallowsEverything } from './robots.js';
|
|
28
|
+
export { buildAuthorizationUrl, exchangeAuthorizationCode, fetchSearchAnalytics, refreshAccessToken, } from './search-console.js';
|
|
26
29
|
export { buildSitemap, SITEMAP_MAX_BYTES, SITEMAP_MAX_URLS, sitemapUrlsFor, } from './sitemap.js';
|
|
27
30
|
export { absoluteUrl, canonicalUrl, hasRoute, normaliseBaseUrl, routeParams } from './url.js';
|
|
28
31
|
export { escapeXmlAttribute, escapeXmlText, renderXmlDocument, renderXmlElement, stripIllegalXmlChars, } from './xml.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAElF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;AAEzF,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE7F,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEhF,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAO1D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAEjE,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAA;AAQ5E,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAQ5B,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,GACf,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE7F,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,UAAU,CAAA"}
|
package/dist/indexable.d.ts
CHANGED
|
@@ -16,7 +16,18 @@ export interface IndexableOptions {
|
|
|
16
16
|
}
|
|
17
17
|
export declare function isPublished(entry: ContentEntry, options?: IndexableOptions): boolean;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Whether a collection declares the conventional `seoNoindex` override field
|
|
20
|
+
* (fiche 13, Task 0 § decision (a) — an ordinary boolean field, never a
|
|
21
|
+
* contract A addition) and this entry has it switched on.
|
|
22
|
+
*
|
|
23
|
+
* Reading it here, in the one gate every output already goes through, is what
|
|
24
|
+
* makes the pitfall this fiche names explicit unavoidable: a page that carries
|
|
25
|
+
* `noindex` in its `<head>` and still lists itself in `/sitemap.xml` is asking
|
|
26
|
+
* a crawler to ignore a URL it is handed in the same breath.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isSeoNoindexed(resource: SeoResource): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Published, not marked `seoNoindex`, and reachable at a URL.
|
|
20
31
|
*
|
|
21
32
|
* A published entry in a collection with no `routing` has nothing to put in a
|
|
22
33
|
* sitemap, and an entry whose route parameters are incomplete — a slug that was
|
package/dist/indexable.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexable.d.ts","sourceRoot":"","sources":["../src/indexable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAGtD;;;;;;;;;GASG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CACpB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAiCxF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"indexable.d.ts","sourceRoot":"","sources":["../src/indexable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAGtD;;;;;;;;;GASG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CACpB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAiCxF;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAI7D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAIT;AAED,0DAA0D;AAC1D,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,SAAS,WAAW,EAAE,EACjC,OAAO,GAAE,gBAAqB,GAC7B,SAAS,WAAW,EAAE,CAExB"}
|
package/dist/indexable.js
CHANGED
|
@@ -34,7 +34,23 @@ export function isPublished(entry, options = {}) {
|
|
|
34
34
|
return at <= (options.now ?? new Date()).getTime();
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Whether a collection declares the conventional `seoNoindex` override field
|
|
38
|
+
* (fiche 13, Task 0 § decision (a) — an ordinary boolean field, never a
|
|
39
|
+
* contract A addition) and this entry has it switched on.
|
|
40
|
+
*
|
|
41
|
+
* Reading it here, in the one gate every output already goes through, is what
|
|
42
|
+
* makes the pitfall this fiche names explicit unavoidable: a page that carries
|
|
43
|
+
* `noindex` in its `<head>` and still lists itself in `/sitemap.xml` is asking
|
|
44
|
+
* a crawler to ignore a URL it is handed in the same breath.
|
|
45
|
+
*/
|
|
46
|
+
export function isSeoNoindexed(resource) {
|
|
47
|
+
const field = resource.collection.fields.seoNoindex;
|
|
48
|
+
if (field === undefined || field.kind !== 'boolean')
|
|
49
|
+
return false;
|
|
50
|
+
return resource.entry.values.seoNoindex === true;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Published, not marked `seoNoindex`, and reachable at a URL.
|
|
38
54
|
*
|
|
39
55
|
* A published entry in a collection with no `routing` has nothing to put in a
|
|
40
56
|
* sitemap, and an entry whose route parameters are incomplete — a slug that was
|
|
@@ -43,6 +59,8 @@ export function isPublished(entry, options = {}) {
|
|
|
43
59
|
export function isIndexable(site, resource, options = {}) {
|
|
44
60
|
if (!isPublished(resource.entry, options))
|
|
45
61
|
return false;
|
|
62
|
+
if (isSeoNoindexed(resource))
|
|
63
|
+
return false;
|
|
46
64
|
return canonicalUrl(site, resource) !== null;
|
|
47
65
|
}
|
|
48
66
|
/** The indexable subset of a list, in the order given. */
|
package/dist/indexable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexable.js","sourceRoot":"","sources":["../src/indexable.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAkBvC,MAAM,UAAU,WAAW,CAAC,KAAmB,EAAE,OAAO,GAAqB,EAAE;IAC7E,0EAA0E;IAC1E,yEAAyE;IACzE,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAA;IAE9C,6EAA6E;IAC7E,2EAA2E;IAC3E,2EAA2E;IAC3E,0CAA0C;IAC1C,IAAI,KAAK,CAAC,KAAK,KAAK,WAAW;QAAE,OAAO,KAAK,CAAA;IAE7C,mEAAmE;IACnE,6EAA6E;IAC7E,4EAA4E;IAC5E,0EAA0E;IAC1E,uEAAuE;IACvE,6EAA6E;IAC7E,0EAA0E;IAC1E,wDAAwD;IACxD,EAAE;IACF,yEAAyE;IACzE,4EAA4E;IAC5E,6EAA6E;IAC7E,2CAA2C;IAC3C,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAE3C,4EAA4E;IAC5E,6EAA6E;IAC7E,cAAc;IACd,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACxC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAA;IAElC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,IAAa,EACb,QAAqB,EACrB,OAAO,GAAqB,EAAE;IAE9B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACvD,OAAO,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAA;AAC9C,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,kBAAkB,CAChC,IAAa,EACb,SAAiC,EACjC,OAAO,GAAqB,EAAE;IAE9B,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;AAC7E,CAAC"}
|
|
1
|
+
{"version":3,"file":"indexable.js","sourceRoot":"","sources":["../src/indexable.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAkBvC,MAAM,UAAU,WAAW,CAAC,KAAmB,EAAE,OAAO,GAAqB,EAAE;IAC7E,0EAA0E;IAC1E,yEAAyE;IACzE,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAA;IAE9C,6EAA6E;IAC7E,2EAA2E;IAC3E,2EAA2E;IAC3E,0CAA0C;IAC1C,IAAI,KAAK,CAAC,KAAK,KAAK,WAAW;QAAE,OAAO,KAAK,CAAA;IAE7C,mEAAmE;IACnE,6EAA6E;IAC7E,4EAA4E;IAC5E,0EAA0E;IAC1E,uEAAuE;IACvE,6EAA6E;IAC7E,0EAA0E;IAC1E,wDAAwD;IACxD,EAAE;IACF,yEAAyE;IACzE,4EAA4E;IAC5E,6EAA6E;IAC7E,2CAA2C;IAC3C,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAE3C,4EAA4E;IAC5E,6EAA6E;IAC7E,cAAc;IACd,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACxC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAA;IAElC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA;AACpD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,QAAqB;IAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAA;IACnD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IACjE,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,KAAK,IAAI,CAAA;AAClD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,IAAa,EACb,QAAqB,EACrB,OAAO,GAAqB,EAAE;IAE9B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACvD,IAAI,cAAc,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1C,OAAO,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAA;AAC9C,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,kBAAkB,CAChC,IAAa,EACb,SAAiC,EACjC,OAAO,GAAqB,EAAE;IAE9B,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;AAC7E,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SeoResource } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Internal link assistant (fiche 70, task 2) — AIOSEO's Link Assistant,
|
|
4
|
+
* without the "recommandation IA" framing: this file finds **candidates**
|
|
5
|
+
* from real, already-published content, never invents an anchor or writes
|
|
6
|
+
* anything (R6 — a suggestion is displayed, never applied automatically; see
|
|
7
|
+
* this file's own test for the orphan/candidate boundary).
|
|
8
|
+
*
|
|
9
|
+
* **Reuses the graph contract A already lets you build.** `extractLinks`
|
|
10
|
+
* (`@cogenta/schema`) was written for the broken-link crawler (L14 task 3)
|
|
11
|
+
* and already walks every shape a link can take — a rich-text `markDefs`
|
|
12
|
+
* `internalLink`, a contract-B action `target`, a plain `url` field — so this
|
|
13
|
+
* file adds nothing new to what counts as "a link"; it only asks a different
|
|
14
|
+
* question of the same graph: not "does this lead somewhere real" but "does
|
|
15
|
+
* anything lead *here*".
|
|
16
|
+
*
|
|
17
|
+
* **Pure, and deliberately not a crawler of its own.** `@cogenta/seo` never
|
|
18
|
+
* touches a database (see this package's own `index.ts` module comment,
|
|
19
|
+
* rule R5) — the caller (`createSeoRouter`'s new `GET
|
|
20
|
+
* /api/seo/link-suggestions` route) does the actual reading through the
|
|
21
|
+
* permission-checked gateway and hands this file the resulting resources, the
|
|
22
|
+
* same shape `SeoDiagnostics` itself is built from.
|
|
23
|
+
*/
|
|
24
|
+
export interface OrphanEntry {
|
|
25
|
+
readonly collection: string;
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly title: string;
|
|
28
|
+
}
|
|
29
|
+
export interface LinkSuggestion {
|
|
30
|
+
readonly collection: string;
|
|
31
|
+
readonly id: string;
|
|
32
|
+
readonly title: string;
|
|
33
|
+
/** How many meaningful title words this candidate shares with the subject entry — a ranking signal, never a score shown as a percentage (the same "no false precision" rule `content-analysis.ts` follows). */
|
|
34
|
+
readonly sharedWordCount: number;
|
|
35
|
+
}
|
|
36
|
+
export interface LinkAssistantReport {
|
|
37
|
+
readonly orphans: readonly OrphanEntry[];
|
|
38
|
+
/** Up to five candidates per entry, keyed by `"collection/id"`. An entry with no plausible candidate is simply absent from the map. */
|
|
39
|
+
readonly suggestionsByEntry: ReadonlyMap<string, readonly LinkSuggestion[]>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Every published, routed resource this site has (across every collection,
|
|
43
|
+
* not only the one an admin is looking at) is what makes "orphan" mean
|
|
44
|
+
* something real: an entry linked only from a *different* collection's page
|
|
45
|
+
* — a homepage's "Latest article" block, say — must not be reported as
|
|
46
|
+
* orphaned just because nothing in its own collection happens to link it.
|
|
47
|
+
* The caller narrows which entries are *reported* to one collection; the
|
|
48
|
+
* graph itself is never narrowed, or the answer would lie.
|
|
49
|
+
*/
|
|
50
|
+
export declare function analyseInternalLinks(resources: readonly SeoResource[]): LinkAssistantReport;
|
|
51
|
+
//# sourceMappingURL=link-assistant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-assistant.d.ts","sourceRoot":"","sources":["../src/link-assistant.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,+MAA+M;IAC/M,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;IACxC,uIAAuI;IACvI,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC,CAAA;CAC5E;AAQD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,SAAS,WAAW,EAAE,GAAG,mBAAmB,CAuE3F"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { extractLinks, queryTokens, titleOf } from '@cogenta/schema';
|
|
2
|
+
const MAX_SUGGESTIONS = 5;
|
|
3
|
+
function keyOf(collection, id) {
|
|
4
|
+
return `${collection}/${id}`;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Every published, routed resource this site has (across every collection,
|
|
8
|
+
* not only the one an admin is looking at) is what makes "orphan" mean
|
|
9
|
+
* something real: an entry linked only from a *different* collection's page
|
|
10
|
+
* — a homepage's "Latest article" block, say — must not be reported as
|
|
11
|
+
* orphaned just because nothing in its own collection happens to link it.
|
|
12
|
+
* The caller narrows which entries are *reported* to one collection; the
|
|
13
|
+
* graph itself is never narrowed, or the answer would lie.
|
|
14
|
+
*/
|
|
15
|
+
export function analyseInternalLinks(resources) {
|
|
16
|
+
const known = new Set(resources.map((resource) => keyOf(resource.collection.name, resource.entry.id)));
|
|
17
|
+
const inbound = new Set();
|
|
18
|
+
for (const resource of resources) {
|
|
19
|
+
const from = keyOf(resource.collection.name, resource.entry.id);
|
|
20
|
+
for (const link of extractLinks(resource.entry)) {
|
|
21
|
+
if (link.kind !== 'entry')
|
|
22
|
+
continue;
|
|
23
|
+
const target = keyOf(link.collection, link.id);
|
|
24
|
+
// A page linking to itself does not un-orphan it — the question this
|
|
25
|
+
// report answers is "does anything *else* lead here".
|
|
26
|
+
if (target === from)
|
|
27
|
+
continue;
|
|
28
|
+
if (known.has(target))
|
|
29
|
+
inbound.add(target);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const orphans = [];
|
|
33
|
+
for (const resource of resources) {
|
|
34
|
+
const key = keyOf(resource.collection.name, resource.entry.id);
|
|
35
|
+
if (inbound.has(key))
|
|
36
|
+
continue;
|
|
37
|
+
orphans.push({
|
|
38
|
+
collection: resource.collection.name,
|
|
39
|
+
id: resource.entry.id,
|
|
40
|
+
title: titleOf(resource.collection, resource.entry),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const byCollection = new Map();
|
|
44
|
+
for (const resource of resources) {
|
|
45
|
+
const list = byCollection.get(resource.collection.name);
|
|
46
|
+
if (list === undefined)
|
|
47
|
+
byCollection.set(resource.collection.name, [resource]);
|
|
48
|
+
else
|
|
49
|
+
list.push(resource);
|
|
50
|
+
}
|
|
51
|
+
const suggestionsByEntry = new Map();
|
|
52
|
+
for (const resource of resources) {
|
|
53
|
+
const subjectTitle = titleOf(resource.collection, resource.entry);
|
|
54
|
+
const subjectWords = new Set(queryTokens(subjectTitle));
|
|
55
|
+
if (subjectWords.size === 0)
|
|
56
|
+
continue;
|
|
57
|
+
const siblings = byCollection.get(resource.collection.name) ?? [];
|
|
58
|
+
const candidates = [];
|
|
59
|
+
for (const sibling of siblings) {
|
|
60
|
+
if (sibling.entry.id === resource.entry.id)
|
|
61
|
+
continue;
|
|
62
|
+
const siblingTitle = titleOf(sibling.collection, sibling.entry);
|
|
63
|
+
const sharedWordCount = new Set(queryTokens(siblingTitle).filter((word) => subjectWords.has(word))).size;
|
|
64
|
+
if (sharedWordCount === 0)
|
|
65
|
+
continue;
|
|
66
|
+
candidates.push({
|
|
67
|
+
collection: sibling.collection.name,
|
|
68
|
+
id: sibling.entry.id,
|
|
69
|
+
title: siblingTitle,
|
|
70
|
+
sharedWordCount,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
candidates.sort((a, b) => b.sharedWordCount - a.sharedWordCount || a.title.localeCompare(b.title));
|
|
74
|
+
if (candidates.length > 0) {
|
|
75
|
+
suggestionsByEntry.set(keyOf(resource.collection.name, resource.entry.id), candidates.slice(0, MAX_SUGGESTIONS));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { orphans, suggestionsByEntry };
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=link-assistant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-assistant.js","sourceRoot":"","sources":["../src/link-assistant.ts"],"names":[],"mappings":"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"}
|
package/dist/metadata.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface MetadataOptions extends IndexableOptions {
|
|
|
32
32
|
readonly resolvers?: SeoResolvers;
|
|
33
33
|
/** The family's alternates, from `buildHreflangMap`. */
|
|
34
34
|
readonly alternates?: readonly HreflangAlternate[];
|
|
35
|
-
/** Overrides the derived title. */
|
|
35
|
+
/** Overrides the derived title, and the entry's own `seoTitle` field. Used for pages that are not one entry. */
|
|
36
36
|
readonly title?: string;
|
|
37
37
|
readonly description?: string;
|
|
38
38
|
/** Overrides the derived social image. */
|
|
@@ -43,6 +43,24 @@ export interface MetadataOptions extends IndexableOptions {
|
|
|
43
43
|
*/
|
|
44
44
|
readonly noindex?: boolean;
|
|
45
45
|
readonly types?: Readonly<Record<string, string>>;
|
|
46
|
+
/**
|
|
47
|
+
* `%title% — %site%`-style template applied to a **derived** title (fiche
|
|
48
|
+
* 13, Task 3). Never applied to an explicit `seoTitle` override or to
|
|
49
|
+
* `options.title`: an editor who types a full SEO title, or a caller who
|
|
50
|
+
* passes one in, means it verbatim — the admin's own character counter
|
|
51
|
+
* counts exactly what was typed, and a silently appended suffix would make
|
|
52
|
+
* that counter lie.
|
|
53
|
+
*/
|
|
54
|
+
readonly titleTemplate?: string;
|
|
55
|
+
/** `titleTemplate`, keyed by collection name. Takes precedence over `titleTemplate` when both apply. */
|
|
56
|
+
readonly collectionTitleTemplates?: Readonly<Record<string, string>>;
|
|
57
|
+
/**
|
|
58
|
+
* Used only when neither `options.image` nor the resource's own
|
|
59
|
+
* `seoImage`/first `media` field resolves to anything — a site-wide
|
|
60
|
+
* default social card (fiche 21 task 3's "Réseaux sociaux" tab), never a
|
|
61
|
+
* per-entry override. A page that has its own image always wins.
|
|
62
|
+
*/
|
|
63
|
+
readonly fallbackImage?: SeoImage;
|
|
46
64
|
}
|
|
47
65
|
export declare function buildMetaTags(site: SeoSite, resource: SeoResource, options?: MetadataOptions): readonly MetaTag[];
|
|
48
66
|
/**
|
package/dist/metadata.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGtD,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAG9E;;;;;;;;;GASG;AAEH,MAAM,MAAM,OAAO,GACf;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClF;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAErD,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAA;IACjC,wDAAwD;IACxD,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAClD,
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGtD,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAG9E;;;;;;;;;GASG;AAEH,MAAM,MAAM,OAAO,GACf;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClF;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAErD,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAA;IACjC,wDAAwD;IACxD,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAClD,gHAAgH;IAChH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,wGAAwG;IACxG,QAAQ,CAAC,wBAAwB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACpE;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAA;CAClC;AAmHD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,eAAoB,GAC5B,SAAS,OAAO,EAAE,CAgIpB;AAUD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAkBD,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAE/D"}
|
package/dist/metadata.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { condense } from '@cogenta/schema';
|
|
2
|
-
import { isPublished } from './indexable.js';
|
|
2
|
+
import { isPublished, isSeoNoindexed } from './indexable.js';
|
|
3
3
|
import { schemaTypeFor } from './json-ld.js';
|
|
4
|
-
import { canonicalUrl } from './url.js';
|
|
4
|
+
import { absoluteUrl, canonicalUrl } from './url.js';
|
|
5
5
|
const TITLE_FIELDS = ['title', 'name', 'label', 'heading'];
|
|
6
6
|
const DESCRIPTION_FIELDS = ['excerpt', 'description', 'summary', 'subtitle', 'teaser'];
|
|
7
|
+
/**
|
|
8
|
+
* The conventional SEO override fields (fiche 13, Task 0 § decision (a)).
|
|
9
|
+
*
|
|
10
|
+
* Checked *before* the derived candidates above, and only ever matched when
|
|
11
|
+
* the collection actually declares a field of this name — an ordinary field
|
|
12
|
+
* a site's own schema adds, never a contract A addition. A collection that
|
|
13
|
+
* does not declare `seoTitle` behaves exactly as it did before this fiche.
|
|
14
|
+
*/
|
|
15
|
+
const SEO_TITLE_FIELDS = ['seoTitle'];
|
|
16
|
+
const SEO_DESCRIPTION_FIELDS = ['seoDescription'];
|
|
17
|
+
const SEO_IMAGE_FIELDS = ['seoImage'];
|
|
7
18
|
/** Google truncates a description near 160 characters; longer is wasted bytes. */
|
|
8
19
|
const MAX_DESCRIPTION = 160;
|
|
9
20
|
function pickString(resource, candidates) {
|
|
@@ -23,10 +34,34 @@ function truncate(value, limit) {
|
|
|
23
34
|
const lastSpace = cut.lastIndexOf(' ');
|
|
24
35
|
return `${(lastSpace > limit / 2 ? cut.slice(0, lastSpace) : cut).trimEnd()}…`;
|
|
25
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* The `titleTemplate` in force for this collection: a per-collection override
|
|
39
|
+
* first, then the site-wide default, `undefined` for neither.
|
|
40
|
+
*/
|
|
41
|
+
function titleTemplateFor(resource, options) {
|
|
42
|
+
return options.collectionTitleTemplates?.[resource.collection.name] ?? options.titleTemplate;
|
|
43
|
+
}
|
|
44
|
+
/** `%title%` and `%site%`, the only two tokens the template understands. */
|
|
45
|
+
function applyTitleTemplate(raw, site, template) {
|
|
46
|
+
if (template === undefined)
|
|
47
|
+
return raw;
|
|
48
|
+
return template.replaceAll('%title%', raw).replaceAll('%site%', site.name);
|
|
49
|
+
}
|
|
26
50
|
function firstImage(resource, resolvers) {
|
|
27
51
|
const resolve = resolvers?.media;
|
|
28
52
|
if (resolve === undefined)
|
|
29
53
|
return undefined;
|
|
54
|
+
for (const name of SEO_IMAGE_FIELDS) {
|
|
55
|
+
if (resource.collection.fields[name] === undefined)
|
|
56
|
+
continue;
|
|
57
|
+
const value = resource.entry.values[name];
|
|
58
|
+
const id = Array.isArray(value) ? value[0] : value;
|
|
59
|
+
if (typeof id !== 'string' || id.length === 0)
|
|
60
|
+
continue;
|
|
61
|
+
const image = resolve(id);
|
|
62
|
+
if (image !== null)
|
|
63
|
+
return image;
|
|
64
|
+
}
|
|
30
65
|
for (const [name, field] of Object.entries(resource.collection.fields)) {
|
|
31
66
|
if (field.kind !== 'media')
|
|
32
67
|
continue;
|
|
@@ -40,6 +75,30 @@ function firstImage(resource, resolvers) {
|
|
|
40
75
|
}
|
|
41
76
|
return undefined;
|
|
42
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* A manually set canonical URL (fiche 13, Task 1's "advanced, collapsed"
|
|
80
|
+
* field), or `null` for "let `canonicalUrl` derive it from routing".
|
|
81
|
+
*
|
|
82
|
+
* Scoped deliberately narrow: it changes the `<link rel="canonical">` this
|
|
83
|
+
* page itself renders (and, with it, `og:url`), but never what `sitemapUrlsFor`
|
|
84
|
+
* lists or what `buildJsonLd` names as `@id` — the same trade-off Yoast makes,
|
|
85
|
+
* and the honest one here too, since resolving "which other resource does
|
|
86
|
+
* this alias" is a real cross-reference this convention does not attempt.
|
|
87
|
+
*/
|
|
88
|
+
function canonicalOverrideOf(resource, site) {
|
|
89
|
+
const field = resource.collection.fields.seoCanonical;
|
|
90
|
+
if (field === undefined || field.kind !== 'text')
|
|
91
|
+
return null;
|
|
92
|
+
const value = resource.entry.values.seoCanonical;
|
|
93
|
+
if (typeof value !== 'string')
|
|
94
|
+
return null;
|
|
95
|
+
const trimmed = value.trim();
|
|
96
|
+
if (trimmed.length === 0)
|
|
97
|
+
return null;
|
|
98
|
+
if (/^https?:\/\//u.test(trimmed))
|
|
99
|
+
return trimmed;
|
|
100
|
+
return absoluteUrl(site, trimmed.startsWith('/') ? trimmed : `/${trimmed}`);
|
|
101
|
+
}
|
|
43
102
|
/**
|
|
44
103
|
* Open Graph's `og:type` vocabulary is not schema.org's, and it is tiny:
|
|
45
104
|
* `article`, `profile`, `website`, `book`, plus the music and video families.
|
|
@@ -59,20 +118,36 @@ function openGraphType(schemaType) {
|
|
|
59
118
|
}
|
|
60
119
|
export function buildMetaTags(site, resource, options = {}) {
|
|
61
120
|
const tags = [];
|
|
62
|
-
const url = canonicalUrl(site, resource);
|
|
121
|
+
const url = canonicalOverrideOf(resource, site) ?? canonicalUrl(site, resource);
|
|
63
122
|
const schemaType = schemaTypeFor(resource.collection, {
|
|
64
123
|
...(options.types === undefined ? {} : { types: options.types }),
|
|
65
124
|
});
|
|
66
|
-
|
|
67
|
-
|
|
125
|
+
// `seoTitle`/`seoDescription`/`seoImage` (fiche 13, Task 0 § decision (a)):
|
|
126
|
+
// read first, and — for the title — never put through the template, which
|
|
127
|
+
// exists to dress up a *derived* title, not to append to one an editor
|
|
128
|
+
// already wrote in full.
|
|
129
|
+
const seoTitleOverride = pickString(resource, SEO_TITLE_FIELDS);
|
|
130
|
+
const derivedTitle = pickString(resource, TITLE_FIELDS) ?? site.name;
|
|
131
|
+
const title = options.title ??
|
|
132
|
+
seoTitleOverride ??
|
|
133
|
+
applyTitleTemplate(derivedTitle, site, titleTemplateFor(resource, options));
|
|
134
|
+
const rawDescription = options.description ??
|
|
135
|
+
pickString(resource, SEO_DESCRIPTION_FIELDS) ??
|
|
136
|
+
pickString(resource, DESCRIPTION_FIELDS) ??
|
|
137
|
+
site.description;
|
|
68
138
|
const description = rawDescription === undefined ? undefined : truncate(rawDescription, MAX_DESCRIPTION);
|
|
69
|
-
const image = options.image ?? firstImage(resource, options.resolvers);
|
|
139
|
+
const image = options.image ?? firstImage(resource, options.resolvers) ?? options.fallbackImage;
|
|
70
140
|
tags.push({ kind: 'title', text: title });
|
|
71
141
|
// The robots tag comes first among the meta tags because it is the one that
|
|
72
142
|
// matters when it is wrong. An unpublished entry rendered through a preview
|
|
73
143
|
// token must carry `noindex`: preview URLs leak — they get pasted into chats,
|
|
74
|
-
// into tickets, and eventually into a crawler's referrer log.
|
|
75
|
-
|
|
144
|
+
// into tickets, and eventually into a crawler's referrer log. A `seoNoindex`
|
|
145
|
+
// override behaves exactly like the explicit `options.noindex` an internal
|
|
146
|
+
// caller (a tag archive, a search results page) already sets.
|
|
147
|
+
const indexable = options.noindex !== true &&
|
|
148
|
+
!isSeoNoindexed(resource) &&
|
|
149
|
+
isPublished(resource.entry, options) &&
|
|
150
|
+
url !== null;
|
|
76
151
|
if (!indexable) {
|
|
77
152
|
tags.push({ kind: 'meta', name: 'robots', content: 'noindex, nofollow' });
|
|
78
153
|
}
|
package/dist/metadata.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
|
package/dist/robots.d.ts
CHANGED
|
@@ -30,6 +30,26 @@ export interface RobotsOptions {
|
|
|
30
30
|
* can find, instead of a `Disallow` buried in a config file.
|
|
31
31
|
*/
|
|
32
32
|
readonly allowIndexing?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* An admin's own hand-written robots.txt lines (fiche 50 task 4), merged
|
|
35
|
+
* in verbatim after the derived group(s) and before the `Sitemap:`
|
|
36
|
+
* directive — the one place in this file `assertSingleLine` deliberately
|
|
37
|
+
* does not apply, since this value is expected to carry real newlines.
|
|
38
|
+
* Trusted syntax: this function does not parse it, only splits it into
|
|
39
|
+
* lines and drops leading/trailing blank ones. Absent or blank contributes
|
|
40
|
+
* nothing, so a site that has never set this renders exactly as before.
|
|
41
|
+
*/
|
|
42
|
+
readonly customRules?: string;
|
|
33
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* True when `text` contains a bare `Disallow: /` for every user agent — the
|
|
46
|
+
* one line that blocks a whole site from every crawler (fiche 50's own named
|
|
47
|
+
* pitfall). Exported so a caller — the admin's custom-rules editor, in
|
|
48
|
+
* particular — can ask for confirmation *before* writing a rule that would
|
|
49
|
+
* de-index the entire site, the same way `allowIndexing: false` is a
|
|
50
|
+
* deliberate, separate choice rather than something a stray line falls into
|
|
51
|
+
* by accident.
|
|
52
|
+
*/
|
|
53
|
+
export declare function robotsRuleDisallowsEverything(text: string): boolean;
|
|
34
54
|
export declare function renderRobotsTxt(options: RobotsOptions): string;
|
|
35
55
|
//# sourceMappingURL=robots.d.ts.map
|
package/dist/robots.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAGzC;;;;;;;;GAQG;AAEH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;IACxC,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAGzC;;;;;;;;GAQG;AAEH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;IACxC,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;IAChC;;;;;;;;OAQG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnE;AAYD,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA0C9D"}
|
package/dist/robots.js
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { CogentaError } from '@cogenta/core';
|
|
2
2
|
import { absoluteUrl } from './url.js';
|
|
3
|
+
/**
|
|
4
|
+
* True when `text` contains a bare `Disallow: /` for every user agent — the
|
|
5
|
+
* one line that blocks a whole site from every crawler (fiche 50's own named
|
|
6
|
+
* pitfall). Exported so a caller — the admin's custom-rules editor, in
|
|
7
|
+
* particular — can ask for confirmation *before* writing a rule that would
|
|
8
|
+
* de-index the entire site, the same way `allowIndexing: false` is a
|
|
9
|
+
* deliberate, separate choice rather than something a stray line falls into
|
|
10
|
+
* by accident.
|
|
11
|
+
*/
|
|
12
|
+
export function robotsRuleDisallowsEverything(text) {
|
|
13
|
+
return /^\s*Disallow:\s*\/\s*$/imu.test(text);
|
|
14
|
+
}
|
|
3
15
|
function assertSingleLine(value, what) {
|
|
4
16
|
if (!/[\n\r]/u.test(value))
|
|
5
17
|
return value;
|
|
@@ -35,6 +47,13 @@ export function renderRobotsTxt(options) {
|
|
|
35
47
|
lines.push('');
|
|
36
48
|
}
|
|
37
49
|
}
|
|
50
|
+
const customRules = (options.customRules ?? '').trim();
|
|
51
|
+
if (customRules !== '') {
|
|
52
|
+
if (lines.at(-1) !== '')
|
|
53
|
+
lines.push('');
|
|
54
|
+
for (const line of customRules.split(/\r\n|\r|\n/u))
|
|
55
|
+
lines.push(line);
|
|
56
|
+
}
|
|
38
57
|
// Sitemap lines are host-level, not group-level, so they go last and outside
|
|
39
58
|
// any group. Put inside one, they are ignored by half the crawlers.
|
|
40
59
|
const sitemaps = options.sitemaps ?? ['/sitemap.xml'];
|
package/dist/robots.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"robots.js","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"robots.js","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** A fetch-shaped function — overridable in tests, defaults to the global `fetch`. */
|
|
2
|
+
export type SearchConsoleFetch = typeof fetch;
|
|
3
|
+
export interface SearchConsoleOAuthOptions {
|
|
4
|
+
readonly clientId: string;
|
|
5
|
+
readonly clientSecret: string;
|
|
6
|
+
/** Must exactly match one of the redirect URIs registered on the Google Cloud OAuth client. */
|
|
7
|
+
readonly redirectUri: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Where a site's admin is sent to grant access. `state` is opaque to this
|
|
11
|
+
* file — the caller mints and verifies it (CSRF protection belongs to
|
|
12
|
+
* whoever owns the session, not to a URL builder) — and `access_type=offline`
|
|
13
|
+
* plus `prompt=consent` are what make Google actually hand back a
|
|
14
|
+
* `refresh_token`; without both, a re-authorization silently omits it.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildAuthorizationUrl(options: SearchConsoleOAuthOptions, state: string): string;
|
|
17
|
+
export interface SearchConsoleTokens {
|
|
18
|
+
readonly accessToken: string;
|
|
19
|
+
readonly refreshToken: string;
|
|
20
|
+
readonly expiresAt: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Exchanges a one-time authorization code for a token pair. Called exactly
|
|
24
|
+
* once per connection, right after Google redirects back with `code` —
|
|
25
|
+
* never retried automatically, since a code is single-use and a retry
|
|
26
|
+
* would only produce a second, equally useless failure.
|
|
27
|
+
*/
|
|
28
|
+
export declare function exchangeAuthorizationCode(options: SearchConsoleOAuthOptions, code: string, fetchImpl?: SearchConsoleFetch): Promise<SearchConsoleTokens>;
|
|
29
|
+
/**
|
|
30
|
+
* Trades a stored refresh token for a fresh access token. Called before
|
|
31
|
+
* every metrics request rather than caching an access token's own expiry
|
|
32
|
+
* (ADR-0032: rapatriés à la demande, not a background poll) — the extra
|
|
33
|
+
* round trip is one request per admin click, not a recurring cost.
|
|
34
|
+
*/
|
|
35
|
+
export declare function refreshAccessToken(options: SearchConsoleOAuthOptions, refreshToken: string, fetchImpl?: SearchConsoleFetch): Promise<{
|
|
36
|
+
readonly accessToken: string;
|
|
37
|
+
readonly expiresAt: string;
|
|
38
|
+
}>;
|
|
39
|
+
export interface SearchConsoleMetricsRow {
|
|
40
|
+
readonly page: string;
|
|
41
|
+
readonly clicks: number;
|
|
42
|
+
readonly impressions: number;
|
|
43
|
+
readonly ctr: number;
|
|
44
|
+
readonly position: number;
|
|
45
|
+
}
|
|
46
|
+
export interface SearchAnalyticsQueryOptions {
|
|
47
|
+
readonly accessToken: string;
|
|
48
|
+
/** The GSC property as registered — a URL-prefix property (`https://example.com/`) or a domain property (`sc-domain:example.com`). */
|
|
49
|
+
readonly siteUrl: string;
|
|
50
|
+
/** `YYYY-MM-DD`. */
|
|
51
|
+
readonly startDate: string;
|
|
52
|
+
readonly endDate: string;
|
|
53
|
+
/** Defaults to 25 — enough for a "top pages" table without an unbounded response. */
|
|
54
|
+
readonly rowLimit?: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Clicks/impressions/CTR/average position per page over one date range —
|
|
58
|
+
* the one read this whole connector exists for. A `POST` to Google's own
|
|
59
|
+
* `searchAnalytics.query`, which Google itself documents as a read
|
|
60
|
+
* operation despite the HTTP verb (there is no `GET` equivalent in this
|
|
61
|
+
* API): no site data is created or changed by calling it, matching
|
|
62
|
+
* ADR-0032's "jamais de soumission... pour limiter la surface de ce que
|
|
63
|
+
* le jeton autorise".
|
|
64
|
+
*/
|
|
65
|
+
export declare function fetchSearchAnalytics(options: SearchAnalyticsQueryOptions, fetchImpl?: SearchConsoleFetch): Promise<readonly SearchConsoleMetricsRow[]>;
|
|
66
|
+
//# sourceMappingURL=search-console.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-console.d.ts","sourceRoot":"","sources":["../src/search-console.ts"],"names":[],"mappings":"AA6BA,sFAAsF;AACtF,MAAM,MAAM,kBAAkB,GAAG,OAAO,KAAK,CAAA;AAE7C,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,+FAA+F;IAC/F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAU/F;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAmBD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,yBAAyB,EAClC,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,kBAA0B,GACpC,OAAO,CAAC,mBAAmB,CAAC,CA0C9B;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,EAClC,YAAY,EAAE,MAAM,EACpB,SAAS,GAAE,kBAA0B,GACpC,OAAO,CAAC;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA4BvE;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,sIAAsI;IACtI,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,oBAAoB;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAaD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,EACpC,SAAS,GAAE,kBAA0B,GACpC,OAAO,CAAC,SAAS,uBAAuB,EAAE,CAAC,CAkC7C"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* Google Search Console connector (fiche 70 task 4, ADR-0032).
|
|
4
|
+
*
|
|
5
|
+
* **`fetch`-only, no Google SDK (R9).** `googleapis` pulls in an auth
|
|
6
|
+
* library, gRPC-adjacent transport code and a dependency tree far larger
|
|
7
|
+
* than the three HTTP calls this file actually needs: build an
|
|
8
|
+
* authorization URL, exchange a code for tokens once, and POST one
|
|
9
|
+
* `searchAnalytics.query` request. All three are plain, documented REST
|
|
10
|
+
* endpoints.
|
|
11
|
+
*
|
|
12
|
+
* **Read-only, structurally.** This file exports no function that could
|
|
13
|
+
* ever submit a sitemap, verify a property or change anything on the
|
|
14
|
+
* Google side — `fetchSearchAnalytics` is the only call that reaches the
|
|
15
|
+
* Search Console API itself, and it is a `POST` to a `query` endpoint that
|
|
16
|
+
* Google's own API classifies as read (ADR-0032 point 4: IndexNow remains
|
|
17
|
+
* the only write path this codebase has toward a search engine).
|
|
18
|
+
*
|
|
19
|
+
* **No state.** Like the rest of `@cogenta/seo`, this module holds no
|
|
20
|
+
* secret and touches no database (rule R5) — `createSearchConsoleConnectionStore`
|
|
21
|
+
* (`@cogenta/schema`) is where a refreshed token is kept; this file only
|
|
22
|
+
* ever receives one as a plain argument and returns a plain result.
|
|
23
|
+
*/
|
|
24
|
+
const AUTHORIZATION_ENDPOINT = 'https://accounts.google.com/o/oauth2/v2/auth';
|
|
25
|
+
const TOKEN_ENDPOINT = 'https://oauth2.googleapis.com/token';
|
|
26
|
+
const SEARCH_ANALYTICS_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly';
|
|
27
|
+
/**
|
|
28
|
+
* Where a site's admin is sent to grant access. `state` is opaque to this
|
|
29
|
+
* file — the caller mints and verifies it (CSRF protection belongs to
|
|
30
|
+
* whoever owns the session, not to a URL builder) — and `access_type=offline`
|
|
31
|
+
* plus `prompt=consent` are what make Google actually hand back a
|
|
32
|
+
* `refresh_token`; without both, a re-authorization silently omits it.
|
|
33
|
+
*/
|
|
34
|
+
export function buildAuthorizationUrl(options, state) {
|
|
35
|
+
const url = new URL(AUTHORIZATION_ENDPOINT);
|
|
36
|
+
url.searchParams.set('client_id', options.clientId);
|
|
37
|
+
url.searchParams.set('redirect_uri', options.redirectUri);
|
|
38
|
+
url.searchParams.set('response_type', 'code');
|
|
39
|
+
url.searchParams.set('scope', SEARCH_ANALYTICS_SCOPE);
|
|
40
|
+
url.searchParams.set('access_type', 'offline');
|
|
41
|
+
url.searchParams.set('prompt', 'consent');
|
|
42
|
+
url.searchParams.set('state', state);
|
|
43
|
+
return url.toString();
|
|
44
|
+
}
|
|
45
|
+
function tokenExchangeFailed(reason, cause) {
|
|
46
|
+
return new CogentaError({
|
|
47
|
+
code: 'SEARCH_CONSOLE_TOKEN_EXCHANGE_FAILED',
|
|
48
|
+
message: `Google's OAuth token endpoint refused the request: ${reason}.`,
|
|
49
|
+
hint: 'Check the OAuth client id/secret and that the redirect URI is registered exactly, then try connecting again.',
|
|
50
|
+
cause,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Exchanges a one-time authorization code for a token pair. Called exactly
|
|
55
|
+
* once per connection, right after Google redirects back with `code` —
|
|
56
|
+
* never retried automatically, since a code is single-use and a retry
|
|
57
|
+
* would only produce a second, equally useless failure.
|
|
58
|
+
*/
|
|
59
|
+
export async function exchangeAuthorizationCode(options, code, fetchImpl = fetch) {
|
|
60
|
+
const response = await fetchImpl(TOKEN_ENDPOINT, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
63
|
+
body: new URLSearchParams({
|
|
64
|
+
code,
|
|
65
|
+
client_id: options.clientId,
|
|
66
|
+
client_secret: options.clientSecret,
|
|
67
|
+
redirect_uri: options.redirectUri,
|
|
68
|
+
grant_type: 'authorization_code',
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
const body = (await response.json().catch(() => ({})));
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
const reason = typeof body.error_description === 'string'
|
|
74
|
+
? body.error_description
|
|
75
|
+
: typeof body.error === 'string'
|
|
76
|
+
? body.error
|
|
77
|
+
: `HTTP ${response.status}`;
|
|
78
|
+
throw tokenExchangeFailed(reason);
|
|
79
|
+
}
|
|
80
|
+
if (typeof body.access_token !== 'string' || typeof body.refresh_token !== 'string') {
|
|
81
|
+
// Google omits `refresh_token` when a user has already granted this
|
|
82
|
+
// app access before and `prompt=consent` was somehow not honoured —
|
|
83
|
+
// named explicitly here rather than left to read as a generic parse
|
|
84
|
+
// failure, since the fix (revoke access at myaccount.google.com/permissions,
|
|
85
|
+
// then reconnect) is different from every other failure this function raises.
|
|
86
|
+
throw tokenExchangeFailed(typeof body.refresh_token !== 'string'
|
|
87
|
+
? "no refresh token was returned — revoke this app's access in the Google account and reconnect"
|
|
88
|
+
: 'the response carried no access token');
|
|
89
|
+
}
|
|
90
|
+
const expiresInSeconds = typeof body.expires_in === 'number' ? body.expires_in : 3600;
|
|
91
|
+
return {
|
|
92
|
+
accessToken: body.access_token,
|
|
93
|
+
refreshToken: body.refresh_token,
|
|
94
|
+
expiresAt: new Date(Date.now() + expiresInSeconds * 1000).toISOString(),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Trades a stored refresh token for a fresh access token. Called before
|
|
99
|
+
* every metrics request rather than caching an access token's own expiry
|
|
100
|
+
* (ADR-0032: rapatriés à la demande, not a background poll) — the extra
|
|
101
|
+
* round trip is one request per admin click, not a recurring cost.
|
|
102
|
+
*/
|
|
103
|
+
export async function refreshAccessToken(options, refreshToken, fetchImpl = fetch) {
|
|
104
|
+
const response = await fetchImpl(TOKEN_ENDPOINT, {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
107
|
+
body: new URLSearchParams({
|
|
108
|
+
refresh_token: refreshToken,
|
|
109
|
+
client_id: options.clientId,
|
|
110
|
+
client_secret: options.clientSecret,
|
|
111
|
+
grant_type: 'refresh_token',
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
const body = (await response.json().catch(() => ({})));
|
|
115
|
+
if (!response.ok || typeof body.access_token !== 'string') {
|
|
116
|
+
const reason = typeof body.error_description === 'string'
|
|
117
|
+
? body.error_description
|
|
118
|
+
: typeof body.error === 'string'
|
|
119
|
+
? body.error
|
|
120
|
+
: `HTTP ${response.status}`;
|
|
121
|
+
throw tokenExchangeFailed(reason);
|
|
122
|
+
}
|
|
123
|
+
const expiresInSeconds = typeof body.expires_in === 'number' ? body.expires_in : 3600;
|
|
124
|
+
return {
|
|
125
|
+
accessToken: body.access_token,
|
|
126
|
+
expiresAt: new Date(Date.now() + expiresInSeconds * 1000).toISOString(),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Clicks/impressions/CTR/average position per page over one date range —
|
|
131
|
+
* the one read this whole connector exists for. A `POST` to Google's own
|
|
132
|
+
* `searchAnalytics.query`, which Google itself documents as a read
|
|
133
|
+
* operation despite the HTTP verb (there is no `GET` equivalent in this
|
|
134
|
+
* API): no site data is created or changed by calling it, matching
|
|
135
|
+
* ADR-0032's "jamais de soumission... pour limiter la surface de ce que
|
|
136
|
+
* le jeton autorise".
|
|
137
|
+
*/
|
|
138
|
+
export async function fetchSearchAnalytics(options, fetchImpl = fetch) {
|
|
139
|
+
const endpoint = `https://www.googleapis.com/webmasters/v3/sites/${encodeURIComponent(options.siteUrl)}/searchAnalytics/query`;
|
|
140
|
+
const response = await fetchImpl(endpoint, {
|
|
141
|
+
method: 'POST',
|
|
142
|
+
headers: {
|
|
143
|
+
authorization: `Bearer ${options.accessToken}`,
|
|
144
|
+
'content-type': 'application/json',
|
|
145
|
+
},
|
|
146
|
+
body: JSON.stringify({
|
|
147
|
+
startDate: options.startDate,
|
|
148
|
+
endDate: options.endDate,
|
|
149
|
+
dimensions: ['page'],
|
|
150
|
+
rowLimit: options.rowLimit ?? 25,
|
|
151
|
+
}),
|
|
152
|
+
});
|
|
153
|
+
const body = (await response.json().catch(() => ({})));
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
throw new CogentaError({
|
|
156
|
+
code: 'SEARCH_CONSOLE_QUERY_FAILED',
|
|
157
|
+
message: `Google Search Console refused the query: ${typeof body.error?.message === 'string' ? body.error.message : `HTTP ${response.status}`}.`,
|
|
158
|
+
hint: 'Confirm the connected Google account is a verified owner of this property in Search Console, then retry.',
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return (body.rows ?? []).map((row) => ({
|
|
162
|
+
page: typeof row.keys?.[0] === 'string' ? row.keys[0] : '',
|
|
163
|
+
clicks: typeof row.clicks === 'number' ? row.clicks : 0,
|
|
164
|
+
impressions: typeof row.impressions === 'number' ? row.impressions : 0,
|
|
165
|
+
ctr: typeof row.ctr === 'number' ? row.ctr : 0,
|
|
166
|
+
position: typeof row.position === 'number' ? row.position : 0,
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=search-console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-console.js","sourceRoot":"","sources":["../src/search-console.ts"],"names":[],"mappings":"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"}
|
package/dist/sitemap.d.ts
CHANGED
|
@@ -33,6 +33,19 @@ export interface SitemapFile {
|
|
|
33
33
|
readonly isIndex: boolean;
|
|
34
34
|
readonly urlCount: number;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* A site's own choice for one collection's contribution to the sitemap
|
|
38
|
+
* (fiche 21 task 3's "Sitemap" tab). `included: false` drops every entry of
|
|
39
|
+
* that collection outright — the same shape `isIndexable` already decides
|
|
40
|
+
* per-entry, just declared once per collection instead of per `seoNoindex`
|
|
41
|
+
* field. `changefreq`/`priority` are hints only (the protocol says crawlers
|
|
42
|
+
* may ignore either), applied to every URL the collection contributes.
|
|
43
|
+
*/
|
|
44
|
+
export interface SitemapCollectionOverride {
|
|
45
|
+
readonly included?: boolean;
|
|
46
|
+
readonly changefreq?: ChangeFrequency;
|
|
47
|
+
readonly priority?: number;
|
|
48
|
+
}
|
|
36
49
|
export interface SitemapOptions extends IndexableOptions {
|
|
37
50
|
readonly maxUrls?: number;
|
|
38
51
|
readonly maxBytes?: number;
|
|
@@ -44,6 +57,8 @@ export interface SitemapOptions extends IndexableOptions {
|
|
|
44
57
|
readonly chunkPath?: (index: number) => string;
|
|
45
58
|
/** `lastmod` of the index itself. Defaults to the newest child `lastmod`. */
|
|
46
59
|
readonly lastmod?: string;
|
|
60
|
+
/** Per-collection inclusion, `changefreq` and `priority`, keyed by collection name. Absent means every collection is included with neither hint set. */
|
|
61
|
+
readonly collectionOverrides?: Readonly<Record<string, SitemapCollectionOverride>>;
|
|
47
62
|
}
|
|
48
63
|
/**
|
|
49
64
|
* The files to write for a set of URLs.
|
package/dist/sitemap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,gBAAgB,CAAA;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAItD;;;;;;;;;GASG;AAEH,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,QAAS,CAAA;AAEtC,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,WAAa,CAAA;AAK3C,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,CAAA;AAEX,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAA;IACrC,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;CACnD;AAED,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,4FAA4F;IAC5F,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,oCAAoC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9C,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,gBAAgB,CAAA;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAItD;;;;;;;;;GASG;AAEH,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,QAAS,CAAA;AAEtC,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,WAAa,CAAA;AAK3C,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,CAAA;AAEX,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAA;IACrC,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;CACnD;AAED,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAA;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,4FAA4F;IAC5F,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,oCAAoC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9C,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,wJAAwJ;IACxJ,QAAQ,CAAC,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAA;CACnF;AAmFD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,SAAS,UAAU,EAAE,EAC3B,OAAO,GAAE,cAAmB,GAC3B,SAAS,WAAW,EAAE,CAyExB;AAWD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,SAAS,WAAW,EAAE,EACjC,OAAO,GAAE,cAAmB,GAC3B,SAAS,UAAU,EAAE,CAuBvB"}
|
package/dist/sitemap.js
CHANGED
|
@@ -180,8 +180,12 @@ function newestLastmod(urls) {
|
|
|
180
180
|
export function sitemapUrlsFor(site, resources, options = {}) {
|
|
181
181
|
const published = indexableResources(site, resources, options);
|
|
182
182
|
const hreflang = buildHreflangMap(site, resources, options);
|
|
183
|
+
const overrides = options.collectionOverrides;
|
|
183
184
|
const urls = [];
|
|
184
185
|
for (const resource of published) {
|
|
186
|
+
const override = overrides?.[resource.collection.name];
|
|
187
|
+
if (override?.included === false)
|
|
188
|
+
continue;
|
|
185
189
|
const loc = canonicalUrl(site, resource);
|
|
186
190
|
if (loc === null)
|
|
187
191
|
continue;
|
|
@@ -189,6 +193,8 @@ export function sitemapUrlsFor(site, resources, options = {}) {
|
|
|
189
193
|
urls.push({
|
|
190
194
|
loc,
|
|
191
195
|
lastmod: resource.entry.updatedAt,
|
|
196
|
+
...(override?.changefreq === undefined ? {} : { changefreq: override.changefreq }),
|
|
197
|
+
...(override?.priority === undefined ? {} : { priority: override.priority }),
|
|
192
198
|
...(alternates === undefined ? {} : { alternates }),
|
|
193
199
|
});
|
|
194
200
|
}
|
package/dist/sitemap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAyB,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAE1E,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAmB,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAEnF;;;;;;;;;GASG;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAEtC,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAA;AAE3C,MAAM,UAAU,GAAG,6CAA6C,CAAA;AAChE,MAAM,QAAQ,GAAG,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAyB,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAE1E,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAmB,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAEnF;;;;;;;;;GASG;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAEtC,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAA;AAE3C,MAAM,UAAU,GAAG,6CAA6C,CAAA;AAChE,MAAM,QAAQ,GAAG,8BAA8B,CAAA;AA2D/C,MAAM,kBAAkB,GAAG,cAAc,CAAA;AACzC,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,YAAY,KAAK,MAAM,CAAA;AAE3E,SAAS,UAAU,CAAC,GAAe;IACjC,MAAM,QAAQ,GAA0B,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAA;IAExE,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;IACpF,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAA;IAC7F,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IACxE,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,GAAG,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,YAAY;YAClB,UAAU,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE;SACrF,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;AAClC,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;IAClD,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AAC3B,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa;IACpB,OAAO,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;AACxE,CAAC;AAED,SAAS,aAAa,CAAC,IAA2B;IAChD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE;QAC1D,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;KAC/B,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CACtB,IAA2B,EAC3B,OAAe,EACf,QAAgB;IAEhB,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAA;IAChC,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,IAAI,OAAO,GAAiB,EAAE,CAAA;IAC9B,IAAI,IAAI,GAAG,QAAQ,CAAA;IAEnB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,yDAAyD;QACzD,MAAM,IAAI,GAAG,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;QAEzD,IAAI,QAAQ,GAAG,IAAI,GAAG,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,YAAY,CAAC;gBACrB,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,+BAA+B,GAAG,CAAC,GAAG,iBAAiB,QAAQ,mBAAmB;gBAC3F,IAAI,EAAE,6GAA6G;gBACnH,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE;aACjD,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ,EAAE,CAAC;YACxD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACpB,OAAO,GAAG,EAAE,CAAA;YACZ,IAAI,GAAG,QAAQ,CAAA;QACjB,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjB,IAAI,IAAI,IAAI,CAAA;IACd,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnE,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAa,EACb,IAA2B,EAC3B,OAAO,GAAmB,EAAE;IAE5B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAA;IACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,iBAAiB,CAAA;IAEtD,IAAI,OAAO,GAAG,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,0DAA0D;YACnE,IAAI,EAAE,gEAAgE,gBAAgB,UAAU,iBAAiB,UAAU;YAC3H,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;SAC/B,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAA;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,gBAAgB,CAAA;IACvD,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;IAEvD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAC5B,OAAO;YACL;gBACE,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,iBAAiB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBAChD,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,IAAI,CAAC,MAAM;aACtB;SACF,CAAA;IACH,CAAC;IAED,6EAA6E;IAC7E,2EAA2E;IAC3E,uEAAuE;IACvE,4EAA4E;IAC5E,iCAAiC;IACjC,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,gBAAgB,CAAA;IACnE,IAAI,MAAM,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACpC,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,kBAAkB,MAAM,CAAC,MAAM,iCAAiC,eAAe,qBAAqB;YAC7G,IAAI,EAAE,0HAA0H;YAChI,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE;SACnD,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,KAAK,GAAkB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5D,IAAI,EAAE,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC7B,QAAQ,EAAE,iBAAiB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,KAAK,CAAC,MAAM;KACvB,CAAC,CAAC,CAAA;IAEH,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAA;IACtD,MAAM,KAAK,GAAe;QACxB,IAAI,EAAE,cAAc;QACpB,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE;QACjC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7B,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;gBACnD,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE;aAClE;SACF,CAAC,CAAC;KACJ,CAAA;IAED,OAAO;QACL;YACE,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,iBAAiB,CAAC,KAAK,CAAC;YAClC,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,KAAK,CAAC,MAAM;SACvB;QACD,GAAG,KAAK;KACT,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAA2B;IAChD,IAAI,MAA0B,CAAA;IAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS;YAAE,SAAQ;QACvC,IAAI,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,GAAG,MAAM;YAAE,MAAM,GAAG,GAAG,CAAC,OAAO,CAAA;IACxE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAa,EACb,SAAiC,EACjC,OAAO,GAAmB,EAAE;IAE5B,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IAC9D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,mBAAmB,CAAA;IAE7C,MAAM,IAAI,GAAiB,EAAE,CAAA;IAC7B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACtD,IAAI,QAAQ,EAAE,QAAQ,KAAK,KAAK;YAAE,SAAQ;QAE1C,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACxC,IAAI,GAAG,KAAK,IAAI;YAAE,SAAQ;QAE1B,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAClD,IAAI,CAAC,IAAI,CAAC;YACR,GAAG;YACH,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS;YACjC,GAAG,CAAC,QAAQ,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;YAClF,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5E,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;SACpD,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cogenta/seo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Sitemaps, feeds, JSON-LD, hreflang and llms.txt derived from the content schema.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"directory": "packages/seo"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cogenta/core": "0.
|
|
31
|
-
"@cogenta/schema": "0.
|
|
30
|
+
"@cogenta/core": "0.6.0",
|
|
31
|
+
"@cogenta/schema": "0.4.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"typescript": "^7.0.2",
|