@jay-framework/seo-validator 0.24.1 → 0.24.2

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.
Files changed (2) hide show
  1. package/dist/index.js +23 -15
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ function isComponent(filePath) {
5
5
  const normalized = filePath.replace(/\\/g, "/");
6
6
  return normalized.includes("/components/");
7
7
  }
8
+ function isSuppressed(ctx, rule) {
9
+ return ctx.validationOverrides?.seo?.[rule] === true;
10
+ }
8
11
  const validate = (ctx) => {
9
12
  const findings = [];
10
13
  const isComp = isComponent(ctx.filePath);
@@ -128,13 +131,16 @@ const validate = (ctx) => {
128
131
  });
129
132
  }
130
133
  if (hasLargeImage && !hasFetchPriorityHigh) {
131
- findings.push({
132
- severity: "warning",
133
- message: 'No image has fetchpriority="high" — the LCP image should be prioritized',
134
- suggestion: 'Add fetchpriority="high" to the largest above-the-fold image (the LCP candidate). This tells the browser to download it first, improving Largest Contentful Paint.',
135
- element: "<img>",
136
- attribute: "fetchpriority"
137
- });
134
+ const suppressLcp = isSuppressed(ctx, "no-lcp-image");
135
+ if (!suppressLcp) {
136
+ findings.push({
137
+ severity: "warning",
138
+ message: 'No image has fetchpriority="high" — the LCP image should be prioritized',
139
+ suggestion: 'Add fetchpriority="high" to the largest above-the-fold image (the LCP candidate). This tells the browser to download it first, improving Largest Contentful Paint. If this page has no LCP image (e.g. text-first hero), suppress with seo: { no-lcp-image: true } in <script type="application/jay-validations">. See agent-kit/designer/validation-guide.md',
140
+ element: "<img>",
141
+ attribute: "fetchpriority"
142
+ });
143
+ }
138
144
  }
139
145
  }
140
146
  const cssSources = [];
@@ -162,12 +168,14 @@ const validate = (ctx) => {
162
168
  while ((importMatch = importRegex.exec(css)) !== null) {
163
169
  const url = importMatch[1] || importMatch[2];
164
170
  if (url.startsWith("https://") || url.startsWith("http://")) {
165
- findings.push({
166
- severity: "warning",
167
- message: `CSS @import of external URL "${url}" creates a chained blocking request that delays page rendering`,
168
- suggestion: 'Move this to a <link rel="stylesheet" href="..."> tag in the HTML <head> instead. This allows the browser preload scanner to discover both resources in parallel.',
169
- element: source === "<style>" ? "<style>" : `<link href="${source}">`
170
- });
171
+ if (!isSuppressed(ctx, "allow-css-import")) {
172
+ findings.push({
173
+ severity: "warning",
174
+ message: `CSS @import of external URL "${url}" creates a chained blocking request that delays page rendering`,
175
+ suggestion: 'Move this to a <link rel="stylesheet" href="..."> tag in the HTML <head> instead. This allows the browser preload scanner to discover both resources in parallel. If intentional, suppress with seo: { allow-css-import: true } in <script type="application/jay-validations">. See agent-kit/designer/validation-guide.md',
176
+ element: source === "<style>" ? "<style>" : `<link href="${source}">`
177
+ });
178
+ }
171
179
  }
172
180
  }
173
181
  }
@@ -210,11 +218,11 @@ const validate = (ctx) => {
210
218
  }
211
219
  const robotsMeta = ctx.head.meta.find((m) => m.name?.toLowerCase() === "robots");
212
220
  const robotsContent = robotsMeta?.content.map((p) => p.value).join("");
213
- if (robotsContent && /noindex/i.test(robotsContent)) {
221
+ if (robotsContent && /noindex/i.test(robotsContent) && !isSuppressed(ctx, "allow-noindex")) {
214
222
  findings.push({
215
223
  severity: "warning",
216
224
  message: 'Page has <meta name="robots" content="noindex"> — it will not appear in search results',
217
- suggestion: "Remove noindex from the robots meta tag if this page should be indexed. If intentional (e.g. admin pages), this warning can be ignored.",
225
+ suggestion: 'Remove noindex from the robots meta tag if this page should be indexed. If intentional, suppress with seo: { allow-noindex: true } in <script type="application/jay-validations">. See agent-kit/designer/validation-guide.md',
218
226
  element: "<meta>",
219
227
  attribute: "content"
220
228
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/seo-validator",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
4
4
  "type": "module",
5
5
  "description": "SEO validation plugin for Jay Framework — checks jay-html templates for SEO best practices",
6
6
  "license": "Apache-2.0",
@@ -24,11 +24,11 @@
24
24
  "test": "vitest run"
25
25
  },
26
26
  "dependencies": {
27
- "@jay-framework/compiler-shared": "^0.24.1"
27
+ "@jay-framework/compiler-shared": "^0.24.2"
28
28
  },
29
29
  "devDependencies": {
30
- "@jay-framework/dev-environment": "^0.24.1",
31
- "@jay-framework/jay-stack-cli": "^0.24.1",
30
+ "@jay-framework/dev-environment": "^0.24.2",
31
+ "@jay-framework/jay-stack-cli": "^0.24.2",
32
32
  "@types/node": "^22.15.21",
33
33
  "node-html-parser": "^6.1.0",
34
34
  "rimraf": "^5.0.5",