@casoon/astro-post-audit 0.2.0 → 0.2.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/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { default, rulesToToml } from './integration.js';
1
+ export { default } from './integration.js';
2
2
  export type { PostAuditOptions, RulesConfig } from './integration.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { default, rulesToToml } from './integration.js';
1
+ export { default } from './integration.js';
@@ -1,103 +1,190 @@
1
1
  import type { AstroIntegration } from 'astro';
2
2
  /**
3
- * Inline rules config that mirrors the Rust rules.toml structure.
3
+ * Inline rules config that mirrors the Rust config structure.
4
4
  * All sections and fields are optional — only set what you want to override.
5
5
  */
6
6
  export interface RulesConfig {
7
+ /** Site-level settings. */
7
8
  site?: {
9
+ /** Base URL for canonical/sitemap checks. Also settable via `site` option or Astro's `site` config. */
8
10
  base_url?: string;
9
11
  };
12
+ /** File filters — glob patterns to include or exclude pages from all checks. */
13
+ filters?: {
14
+ /** Only check files matching these glob patterns. Merged with the top-level `include` option. */
15
+ include?: string[];
16
+ /** Skip files matching these glob patterns (e.g. `["404.html", "drafts/**"]`). Merged with the top-level `exclude` option. */
17
+ exclude?: string[];
18
+ };
19
+ /** URL normalization rules for internal link and canonical consistency. */
10
20
  url_normalization?: {
21
+ /** Trailing slash policy. `"always"`: require trailing slash, `"never"`: forbid, `"ignore"`: no check. @default "always" */
11
22
  trailing_slash?: 'always' | 'never' | 'ignore';
23
+ /** Whether `index.html` in URLs is allowed. `"forbid"`: warn on `/page/index.html` links, `"allow"`: permit them. @default "forbid" */
12
24
  index_html?: 'forbid' | 'allow';
13
25
  };
26
+ /** Canonical `<link rel="canonical">` tag checks. */
14
27
  canonical?: {
28
+ /** Every page must have a canonical tag. @default true */
15
29
  require?: boolean;
30
+ /** Canonical URL must be absolute (not relative). @default true */
16
31
  absolute?: boolean;
32
+ /** Canonical must point to the same origin as `site`. @default true */
17
33
  same_origin?: boolean;
34
+ /** Canonical must be a self-reference (point to the page itself). @default false */
18
35
  self_reference?: boolean;
19
36
  };
37
+ /** Robots meta tag checks. */
20
38
  robots_meta?: {
39
+ /** Don't warn on pages with `noindex`. @default true */
21
40
  allow_noindex?: boolean;
41
+ /** Treat any `noindex` page as an error. @default false */
22
42
  fail_if_noindex?: boolean;
23
43
  };
44
+ /** Internal link consistency checks. */
24
45
  links?: {
46
+ /** Check that internal links resolve to existing pages. @default true */
25
47
  check_internal?: boolean;
48
+ /** Broken internal links are errors (not just warnings). @default true */
26
49
  fail_on_broken?: boolean;
50
+ /** Warn on query parameters (`?foo=bar`) in internal links. @default true */
27
51
  forbid_query_params_internal?: boolean;
52
+ /** Validate that `#fragment` targets exist in the linked page. @default false */
28
53
  check_fragments?: boolean;
54
+ /** Warn about pages with no incoming internal links (orphan pages). @default false */
29
55
  detect_orphan_pages?: boolean;
56
+ /** Warn on `http://` in internal links (mixed content). @default true */
30
57
  check_mixed_content?: boolean;
31
58
  };
59
+ /** Sitemap cross-reference checks. */
32
60
  sitemap?: {
61
+ /** `sitemap.xml` must exist in `dist/`. @default false */
33
62
  require?: boolean;
63
+ /** Canonical URLs should appear in the sitemap. @default true */
34
64
  canonical_must_be_in_sitemap?: boolean;
65
+ /** Sitemap must not contain non-canonical URLs. @default false */
35
66
  forbid_noncanonical_in_sitemap?: boolean;
67
+ /** Every sitemap URL must correspond to a page in `dist/`. @default true */
36
68
  entries_must_exist_in_dist?: boolean;
37
69
  };
70
+ /** `robots.txt` file checks. */
38
71
  robots_txt?: {
72
+ /** `robots.txt` must exist. @default false */
39
73
  require?: boolean;
74
+ /** `robots.txt` must contain a link to the sitemap. @default false */
40
75
  require_sitemap_link?: boolean;
41
76
  };
77
+ /** Basic HTML structure checks. */
42
78
  html_basics?: {
79
+ /** `<html lang="...">` attribute is required. @default true */
43
80
  lang_attr_required?: boolean;
81
+ /** `<title>` tag is required and must be non-empty. @default true */
44
82
  title_required?: boolean;
83
+ /** `<meta name="description">` is required. @default false */
45
84
  meta_description_required?: boolean;
85
+ /** `<meta name="viewport">` is required. @default true */
46
86
  viewport_required?: boolean;
87
+ /** Warn if `<title>` exceeds this character length. @default 60 */
47
88
  title_max_length?: number;
89
+ /** Warn if meta description exceeds this character length. @default 160 */
48
90
  meta_description_max_length?: number;
49
91
  };
92
+ /** Heading hierarchy checks. */
50
93
  headings?: {
94
+ /** Page must have at least one `<h1>`. @default true */
51
95
  require_h1?: boolean;
96
+ /** Only one `<h1>` per page. @default true */
52
97
  single_h1?: boolean;
98
+ /** No heading level gaps (e.g. `<h2>` followed by `<h4>`). @default false */
53
99
  no_skip?: boolean;
54
100
  };
101
+ /** Accessibility (a11y) heuristics — static checks, no layout computation. */
55
102
  a11y?: {
103
+ /** `<img>` elements must have an `alt` attribute. @default true */
56
104
  img_alt_required?: boolean;
105
+ /** Allow images with `role="presentation"` or `aria-hidden="true"` to skip `alt`. @default true */
57
106
  allow_decorative_images?: boolean;
107
+ /** `<a>` elements must have an accessible name (text, `aria-label`, or `aria-labelledby`). @default true */
58
108
  a_accessible_name_required?: boolean;
109
+ /** `<button>` elements must have an accessible name. @default true */
59
110
  button_name_required?: boolean;
111
+ /** Form controls must have an associated `<label>`. @default true */
60
112
  label_for_required?: boolean;
113
+ /** Warn on generic link text like "click here", "mehr", "weiter". @default true */
61
114
  warn_generic_link_text?: boolean;
115
+ /** Warn if `aria-hidden="true"` is set on a focusable element. @default true */
62
116
  aria_hidden_focusable_check?: boolean;
117
+ /** Require a skip navigation link (e.g. `<a href="#main-content">`). @default false */
63
118
  require_skip_link?: boolean;
64
119
  };
120
+ /** Asset reference and size checks. Enable via `checkAssets` option or set fields here. */
65
121
  assets?: {
122
+ /** Check that `<img>`, `<script>`, `<link>` references resolve to files in `dist/`. @default false */
66
123
  check_broken_assets?: boolean;
124
+ /** Warn if `<img>` is missing `width`/`height` attributes (CLS prevention). @default false */
67
125
  check_image_dimensions?: boolean;
126
+ /** Warn if any image file exceeds this size in KB. Off by default. */
68
127
  max_image_size_kb?: number;
128
+ /** Warn if any JS file exceeds this size in KB. Off by default. */
69
129
  max_js_size_kb?: number;
130
+ /** Warn if any CSS file exceeds this size in KB. Off by default. */
70
131
  max_css_size_kb?: number;
132
+ /** Warn if asset filenames lack a cache-busting hash. @default false */
71
133
  require_hashed_filenames?: boolean;
72
134
  };
135
+ /** Open Graph and Twitter Card meta tag checks. */
73
136
  opengraph?: {
137
+ /** Require `og:title` meta tag. @default false */
74
138
  require_og_title?: boolean;
139
+ /** Require `og:description` meta tag. @default false */
75
140
  require_og_description?: boolean;
141
+ /** Require `og:image` meta tag. @default false */
76
142
  require_og_image?: boolean;
143
+ /** Require `twitter:card` meta tag. @default false */
77
144
  require_twitter_card?: boolean;
78
145
  };
146
+ /** Structured data (JSON-LD) validation. Enable via `checkStructuredData` option or set fields here. */
79
147
  structured_data?: {
148
+ /** Validate JSON-LD syntax and semantics (`@context`, `@type`, required properties). @default false */
80
149
  check_json_ld?: boolean;
150
+ /** Every page must contain at least one JSON-LD block. @default false */
81
151
  require_json_ld?: boolean;
82
152
  };
153
+ /** Hreflang checks for multilingual sites. */
83
154
  hreflang?: {
155
+ /** Enable hreflang link checks. @default false */
84
156
  check_hreflang?: boolean;
157
+ /** Require an `x-default` hreflang entry. @default false */
85
158
  require_x_default?: boolean;
159
+ /** Hreflang must include a self-referencing entry. @default false */
86
160
  require_self_reference?: boolean;
161
+ /** Hreflang links must be reciprocal (A→B and B→A). @default false */
87
162
  require_reciprocal?: boolean;
88
163
  };
164
+ /** Security heuristic checks. Enable via `checkSecurity` option or set fields here. */
89
165
  security?: {
166
+ /** Warn on `target="_blank"` without `rel="noopener"`. @default true */
90
167
  check_target_blank?: boolean;
168
+ /** Warn on `http://` resource URLs (mixed content). @default true */
91
169
  check_mixed_content?: boolean;
170
+ /** Warn on inline `<script>` tags. @default false */
92
171
  warn_inline_scripts?: boolean;
93
172
  };
173
+ /** Duplicate content detection. Enable via `checkDuplicates` option or set fields here. */
94
174
  content_quality?: {
175
+ /** Warn if multiple pages share the same `<title>`. @default false */
95
176
  detect_duplicate_titles?: boolean;
177
+ /** Warn if multiple pages share the same meta description. @default false */
96
178
  detect_duplicate_descriptions?: boolean;
179
+ /** Warn if multiple pages share the same `<h1>`. @default false */
97
180
  detect_duplicate_h1?: boolean;
181
+ /** Warn if pages have identical content (by hash). @default false */
98
182
  detect_duplicate_pages?: boolean;
99
183
  };
100
- /** Custom severity overrides per rule ID. Maps rule IDs to 'error' | 'warning' | 'info' | 'off'. */
184
+ /**
185
+ * Override severity per rule ID.
186
+ * @example `{ "html/title-too-long": "off", "a11y/img-alt-missing": "error" }`
187
+ */
101
188
  severity?: Record<string, 'error' | 'warning' | 'info' | 'off'>;
102
189
  /** @deprecated Not yet implemented — will be ignored. */
103
190
  external_links?: {
@@ -110,9 +197,9 @@ export interface RulesConfig {
110
197
  };
111
198
  }
112
199
  export interface PostAuditOptions {
113
- /** Path to rules.toml config file. Mutually exclusive with `rules`. */
200
+ /** Path to a TOML config file. Mutually exclusive with `rules`. */
114
201
  config?: string;
115
- /** Inline rules config (generates a temporary rules.toml). Mutually exclusive with `config`. */
202
+ /** Inline rules config. Mutually exclusive with `config`. */
116
203
  rules?: RulesConfig;
117
204
  /** Base URL (auto-detected from Astro's `site` config if not set) */
118
205
  site?: string;
@@ -143,10 +230,5 @@ export interface PostAuditOptions {
143
230
  /** Throw an AstroError when the audit finds errors (fails the build). Default: false */
144
231
  throwOnError?: boolean;
145
232
  }
146
- /**
147
- * Serialize a RulesConfig object to TOML format.
148
- * @internal Exported for testing only.
149
- */
150
- export declare function rulesToToml(rules: RulesConfig): string;
151
233
  export default function postAudit(options?: PostAuditOptions): AstroIntegration;
152
234
  //# sourceMappingURL=integration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../src/integration.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../src/integration.ts"],"names":[],"mappings":"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"}
@@ -1,38 +1,7 @@
1
1
  import { execFileSync } from 'node:child_process';
2
- import { existsSync, mkdtempSync, writeFileSync, unlinkSync, rmdirSync } from 'node:fs';
2
+ import { existsSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
- import { tmpdir } from 'node:os';
5
4
  import { fileURLToPath } from 'node:url';
6
- /**
7
- * Serialize a RulesConfig object to TOML format.
8
- * @internal Exported for testing only.
9
- */
10
- export function rulesToToml(rules) {
11
- const lines = [];
12
- for (const [section, values] of Object.entries(rules)) {
13
- if (values == null || typeof values !== 'object')
14
- continue;
15
- lines.push(`[${section}]`);
16
- for (const [key, val] of Object.entries(values)) {
17
- if (val === undefined)
18
- continue;
19
- // Quote keys that contain special chars (e.g. rule IDs like "html/lang-missing")
20
- const tomlKey = /^[a-zA-Z0-9_-]+$/.test(key) ? key : `"${key}"`;
21
- if (typeof val === 'string') {
22
- lines.push(`${tomlKey} = "${val}"`);
23
- }
24
- else if (Array.isArray(val)) {
25
- const items = val.map((v) => `"${v}"`).join(', ');
26
- lines.push(`${tomlKey} = [${items}]`);
27
- }
28
- else {
29
- lines.push(`${tomlKey} = ${val}`);
30
- }
31
- }
32
- lines.push('');
33
- }
34
- return lines.join('\n');
35
- }
36
5
  function resolveBinaryPath() {
37
6
  const binDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'bin');
38
7
  const binaryName = process.platform === 'win32' ? 'astro-post-audit.exe' : 'astro-post-audit';
@@ -53,7 +22,7 @@ export default function postAudit(options = {}) {
53
22
  // Validate mutual exclusion: config and rules cannot both be set
54
23
  if (options.config && options.rules) {
55
24
  throw new Error('astro-post-audit: "config" and "rules" are mutually exclusive. ' +
56
- 'Use "config" to point to a rules.toml file, OR use "rules" to provide inline config — not both.');
25
+ 'Use "config" to point to a config file, OR use "rules" to provide inline config — not both.');
57
26
  }
58
27
  // Validate that rules is a non-empty object if provided
59
28
  if (options.rules && typeof options.rules === 'object' && Object.keys(options.rules).length === 0) {
@@ -101,20 +70,21 @@ export default function postAudit(options = {}) {
101
70
  args.push('--exclude', pattern);
102
71
  }
103
72
  }
104
- // Config: explicit file path OR generate temp from inline rules
105
- let tempConfigPath;
73
+ // Config: explicit file path OR pipe inline rules via stdin
74
+ let stdinInput;
106
75
  if (options.config) {
107
76
  args.push('--config', options.config);
108
77
  }
109
78
  else if (options.rules) {
110
- const tempDir = mkdtempSync(join(tmpdir(), 'astro-post-audit-'));
111
- tempConfigPath = join(tempDir, 'rules.toml');
112
- writeFileSync(tempConfigPath, rulesToToml(options.rules), 'utf-8');
113
- args.push('--config', tempConfigPath);
79
+ args.push('--config-stdin');
80
+ stdinInput = JSON.stringify(options.rules);
114
81
  }
115
82
  logger.info('Running post-build audit...');
116
83
  try {
117
- execFileSync(binaryPath, args, { stdio: 'inherit' });
84
+ execFileSync(binaryPath, args, {
85
+ stdio: stdinInput ? ['pipe', 'inherit', 'inherit'] : 'inherit',
86
+ input: stdinInput,
87
+ });
118
88
  logger.info('All checks passed!');
119
89
  }
120
90
  catch (err) {
@@ -131,18 +101,6 @@ export default function postAudit(options = {}) {
131
101
  logger.error(`Audit failed with exit code ${exitCode ?? 'unknown'}`);
132
102
  }
133
103
  }
134
- finally {
135
- // Clean up temp config
136
- if (tempConfigPath) {
137
- try {
138
- unlinkSync(tempConfigPath);
139
- rmdirSync(dirname(tempConfigPath));
140
- }
141
- catch {
142
- // ignore cleanup errors
143
- }
144
- }
145
- }
146
104
  },
147
105
  },
148
106
  };
@@ -1,72 +1,6 @@
1
1
  import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import postAudit, { rulesToToml } from './integration.js';
4
- // ==========================================================================
5
- // rulesToToml serialization
6
- // ==========================================================================
7
- describe('rulesToToml', () => {
8
- it('serializes boolean values', () => {
9
- const rules = {
10
- canonical: { require: true, absolute: false },
11
- };
12
- const toml = rulesToToml(rules);
13
- assert.ok(toml.includes('[canonical]'));
14
- assert.ok(toml.includes('require = true'));
15
- assert.ok(toml.includes('absolute = false'));
16
- });
17
- it('serializes string values with quotes', () => {
18
- const rules = {
19
- url_normalization: { trailing_slash: 'always', index_html: 'forbid' },
20
- };
21
- const toml = rulesToToml(rules);
22
- assert.ok(toml.includes('[url_normalization]'));
23
- assert.ok(toml.includes('trailing_slash = "always"'));
24
- assert.ok(toml.includes('index_html = "forbid"'));
25
- });
26
- it('serializes numeric values', () => {
27
- const rules = {
28
- html_basics: { title_max_length: 60, meta_description_max_length: 160 },
29
- };
30
- const toml = rulesToToml(rules);
31
- assert.ok(toml.includes('title_max_length = 60'));
32
- assert.ok(toml.includes('meta_description_max_length = 160'));
33
- });
34
- it('serializes array values', () => {
35
- const rules = {
36
- external_links: {
37
- allow_domains: ['example.com', 'test.org'],
38
- },
39
- };
40
- const toml = rulesToToml(rules);
41
- assert.ok(toml.includes('[external_links]'));
42
- assert.ok(toml.includes('allow_domains = ["example.com", "test.org"]'));
43
- });
44
- it('skips undefined values', () => {
45
- const rules = {
46
- canonical: { require: true },
47
- };
48
- const toml = rulesToToml(rules);
49
- // Only 'require' should be present, not 'absolute', 'same_origin', 'self_reference'
50
- assert.ok(toml.includes('require = true'));
51
- assert.ok(!toml.includes('absolute'));
52
- assert.ok(!toml.includes('same_origin'));
53
- });
54
- it('handles empty rules', () => {
55
- const toml = rulesToToml({});
56
- assert.equal(toml, '');
57
- });
58
- it('handles multiple sections', () => {
59
- const rules = {
60
- canonical: { require: true },
61
- headings: { require_h1: true, single_h1: false },
62
- };
63
- const toml = rulesToToml(rules);
64
- assert.ok(toml.includes('[canonical]'));
65
- assert.ok(toml.includes('[headings]'));
66
- assert.ok(toml.includes('require_h1 = true'));
67
- assert.ok(toml.includes('single_h1 = false'));
68
- });
69
- });
3
+ import postAudit from './integration.js';
70
4
  // ==========================================================================
71
5
  // postAudit integration factory
72
6
  // ==========================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@casoon/astro-post-audit",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Astro integration for post-build auditing: SEO, links, and lightweight WCAG checks",
5
5
  "license": "MIT",
6
6
  "type": "module",