@aeptus/aexeo-emdash 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,57 @@ and the project follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.5.0] - 2026-05-01
10
+
11
+ Three follow-ups from real-world adoption feedback after 0.4.0:
12
+
13
+ - richer suppression selectors so editors can target by collection
14
+ and document status, not just route + rule
15
+ - ergonomic collections API (`includeCollections` /
16
+ `excludeCollections`) for sites whose schema is close to the
17
+ default but needs minor tweaks
18
+ - README now leads with the suppressions glob semantics so consumers
19
+ migrating from local patches don't have to dig through the
20
+ CHANGELOG to learn that `*` is single-segment and `**` is recursive
21
+
22
+ **Compatibility:** verified against emdash `0.7.0` and `0.8.0`.
23
+
24
+ ### Added
25
+
26
+ - **`Suppression.collections`** — silence findings for documents in
27
+ the named emdash collections.
28
+ - **`Suppression.statuses`** — silence findings for documents in the
29
+ named statuses (`"draft"`, `"published"`, etc.). Useful for
30
+ preventing draft-stage findings from cluttering the dashboard.
31
+ - **`includeCollections`** factory option — adds slugs to the
32
+ default `["posts", "pages"]`. For sites that have the defaults
33
+ PLUS extras (e.g. blog adapter + `guides` and `faqs`).
34
+ - **`excludeCollections`** factory option — removes slugs from the
35
+ default. For sites that have most of the defaults but want to
36
+ skip one.
37
+
38
+ ### Changed
39
+
40
+ - **`SuppressionFilter.apply` signature** — now takes a
41
+ `SuppressionContext` object (`{ route, collection?, status? }`)
42
+ instead of a bare route string. Direct callers of `apply` will
43
+ see a TypeScript error and need a one-line update; the public
44
+ factory API (`aexeoPlugin({ suppressions })`) is unchanged.
45
+
46
+ ### Notes for hosts upgrading from 0.4.x
47
+
48
+ - No automatic behavior change. New selectors and options default
49
+ to undefined and are ignored unless the host opts in.
50
+ - Selector matching is **AND across selectors, OR across rules**.
51
+ A suppression with both `routePattern: "/fr-fr/**"` and
52
+ `collections: ["pages"]` only silences findings on French pages,
53
+ not on French blog posts.
54
+ - Sitewide findings (route `*`) ignore `collections` /
55
+ `statuses` selectors — those findings are inherently
56
+ cross-document and have no single collection or status to match.
57
+ Use `routePattern` (or omit it) and `ruleIds` for sitewide
58
+ suppressions.
59
+
9
60
  ## [0.4.0] - 2026-05-01
10
61
 
11
62
  Adds upstreamed support for editor-workflow finding suppressions.
@@ -16,13 +67,13 @@ patch over the published plugin.
16
67
 
17
68
  ### Added
18
69
 
19
- - **`seogeoPlugin({ suppressions })` option.** Each rule silences
70
+ - **`aexeoPlugin({ suppressions })` option.** Each rule silences
20
71
  findings matching the route pattern (glob) AND/OR a rule-id set.
21
72
  Applied before findings are persisted to KV — suppressed findings
22
73
  never reach the dashboard, /findings, or the per-document panel.
23
74
 
24
75
  ```ts
25
- seogeoPlugin({
76
+ aexeoPlugin({
26
77
  suppressions: [
27
78
  { routePattern: "/privacy", ruleIds: ["RULE001"] },
28
79
  { routePattern: "/fr-fr/**", ruleIds: ["RULE002"] },
@@ -50,7 +101,7 @@ patch over the published plugin.
50
101
  and the filter is a no-op until the host opts in.
51
102
  - Suppressions are plugin-only by design. The CLI `check` continues
52
103
  to surface every finding; if you want to silence findings at the
53
- CLI layer, use `seogeo.toml`'s `[ignore]` block. The two surfaces
104
+ CLI layer, use `aexeo.toml`'s `[ignore]` block. The two surfaces
54
105
  serve different audiences: the plugin is editorial workflow, the
55
106
  CLI is build-gating.
56
107
 
@@ -144,10 +195,10 @@ Block Kit (no link needs there).
144
195
  emdash's `usePluginPage` hook picks this up and renders the
145
196
  React component in place of the Block Kit fallback.
146
197
  - **Two new HTTP routes** the React component consumes:
147
- - `POST /_emdash/api/plugins/aexeo-seogeo/data` — read current
198
+ - `POST /_emdash/api/plugins/aexeo-emdash/data` — read current
148
199
  findings + per-route metadata + computed URLs (no
149
200
  re-evaluation).
150
- - `POST /_emdash/api/plugins/aexeo-seogeo/refresh` — sweep the
201
+ - `POST /_emdash/api/plugins/aexeo-emdash/refresh` — sweep the
151
202
  configured collections, write findings to KV, return the same
152
203
  payload as `/data` plus a refresh summary.
153
204
  Both routes return JSON in the shape exported as `FindingsPayload`
@@ -192,7 +243,7 @@ rule-engine change).
192
243
 
193
244
  ### Added
194
245
 
195
- - **`seogeoPlugin({ collections })` option** for configured mode.
246
+ - **`aexeoPlugin({ collections })` option** for configured mode.
196
247
  Lets sites with non-default collection slugs override which
197
248
  collections the Refresh button sweeps. Defaults to
198
249
  `["posts", "pages"]` when omitted (the slugs from
@@ -230,15 +281,15 @@ First public release.
230
281
 
231
282
  ### Added
232
283
 
233
- - `seogeoPlugin()` factory for **configured mode** — the recommended
284
+ - `aexeoPlugin()` factory for **configured mode** — the recommended
234
285
  install path for first-party emdash sites. Plugin runs in-process
235
286
  inside the host Worker. No sidecar deploy, no auth token, no admin
236
287
  Setup page.
237
- - `seogeoPluginSandboxed({ evaluatorHost })` factory for **sandboxed
288
+ - `aexeoPluginSandboxed({ evaluatorHost })` factory for **sandboxed
238
289
  mode** — preserved for future third-party-deploy scenarios where
239
290
  the plugin code shouldn't have full host access. Requires a
240
291
  separately-deployed sidecar Worker (template at
241
- `seogeo-crawl-worker` in the source repo).
292
+ `aexeo-crawl-worker` in the source repo).
242
293
  - Block Kit admin pages: findings table, per-document panel,
243
294
  intelligence-score dashboard widget. Refresh button on the
244
295
  findings page sweeps every document in the configured collections.
@@ -246,7 +297,7 @@ First public release.
246
297
  automatic re-evaluation of the changed document and update the
247
298
  findings table without manual intervention.
248
299
  - WASM-backed evaluator powered by the `aexeo-emdash-bridge` Rust
249
- crate (same engine as the seogeo CLI). Compiles via the consumer's
300
+ crate (same engine as the Aexeo CLI). Compiles via the consumer's
250
301
  Vite/Wrangler chain — `vite-plugin-wasm` is a peer-side runtime
251
302
  dependency for Vite-driven Cloudflare deploys.
252
303
 
@@ -266,7 +317,8 @@ First public release.
266
317
  `astro.config.mjs` for the WASM import to resolve to a
267
318
  precompiled `WebAssembly.Module`. Not optional.
268
319
 
269
- [Unreleased]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.4.0...HEAD
320
+ [Unreleased]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.5.0...HEAD
321
+ [0.5.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.4.0...aexeo-emdash-v0.5.0
270
322
  [0.4.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.3.0...aexeo-emdash-v0.4.0
271
323
  [0.3.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.2.0...aexeo-emdash-v0.3.0
272
324
  [0.2.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.1.2...aexeo-emdash-v0.2.0
package/INSTALL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Installing `@aeptus/aexeo-emdash`
2
2
 
3
- This package adds Aexeo's seogeo SEO/GEO content evaluator to an emdash
3
+ This package adds Aexeo SEO/GEO content evaluation to an emdash
4
4
  site. Findings show up as a Block Kit admin page; a sidebar widget
5
5
  shows the site's current intelligence score; saves auto-evaluate the
6
6
  changed document.
@@ -9,11 +9,11 @@ changed document.
9
9
 
10
10
  The package exports two factories:
11
11
 
12
- - **`seogeoPlugin()`** — **configured mode** (recommended). Plugin
12
+ - **`aexeoPlugin()`** — **configured mode** (recommended). Plugin
13
13
  runs in-process inside the host emdash Worker. No separate
14
14
  deployment, no auth token, no admin Setup page. Use this for
15
15
  first-party emdash sites.
16
- - **`seogeoPluginSandboxed({ evaluatorHost })`** — **sandboxed
16
+ - **`aexeoPluginSandboxed({ evaluatorHost })`** — **sandboxed
17
17
  mode**. Plugin runs inside emdash's Worker Loader isolate; WASM
18
18
  evaluation runs in a separate sidecar Worker the operator
19
19
  deploys. Use this only when a third party hosts emdash and
@@ -42,7 +42,7 @@ npm install @aeptus/aexeo-emdash vite-plugin-wasm
42
42
  `vite-plugin-wasm` is required because Vite's defaults treat `.wasm`
43
43
  imports as static-asset URLs, but Cloudflare Workers can only run
44
44
  WASM as precompiled `WebAssembly.Module` instances. The plugin
45
- bridges the two; without it, the seogeo plugin's first call throws
45
+ bridges the two; without it, the Aexeo plugin's first call throws
46
46
  "WASM module did not resolve to a WebAssembly.Module."
47
47
 
48
48
  > **If installing from a private git remote or as a vendored
@@ -54,7 +54,7 @@ bridges the two; without it, the seogeo plugin's first call throws
54
54
  ```js
55
55
  import cloudflare from "@astrojs/cloudflare";
56
56
  import { d1, r2 } from "@emdash-cms/cloudflare";
57
- import { seogeoPlugin } from "@aeptus/aexeo-emdash";
57
+ import { aexeoPlugin } from "@aeptus/aexeo-emdash";
58
58
  import { defineConfig } from "astro/config";
59
59
  import emdash from "emdash/astro";
60
60
  import wasm from "vite-plugin-wasm";
@@ -68,7 +68,7 @@ export default defineConfig({
68
68
  // workerd disallow runtime WebAssembly.instantiate from raw
69
69
  // bytes, so the bundler has to do the compilation.
70
70
  plugins: [wasm()],
71
- // The seogeo plugin's WASM import confuses Vite's dep
71
+ // The Aexeo plugin's WASM import confuses Vite's dep
72
72
  // optimizer when it tries to pre-bundle the package.
73
73
  optimizeDeps: { exclude: ["@aeptus/aexeo-emdash"] },
74
74
  },
@@ -76,7 +76,7 @@ export default defineConfig({
76
76
  emdash({
77
77
  database: d1({ binding: "DB" }),
78
78
  storage: r2({ binding: "MEDIA" }),
79
- plugins: [seogeoPlugin()],
79
+ plugins: [aexeoPlugin()],
80
80
  }),
81
81
  ],
82
82
  });
@@ -96,7 +96,7 @@ no sidecar to deploy.
96
96
  http://localhost:4321/_emdash/admin/plugins
97
97
  ```
98
98
 
99
- The seogeo plugin will appear in the list. Click it.
99
+ The Aexeo plugin will appear in the list. Click it.
100
100
 
101
101
  3. The findings page renders with a Refresh button. Click **Refresh**
102
102
  — toast says "Refreshed N routes (M findings across K documents)"
@@ -151,7 +151,7 @@ token to rotate, no Setup page to revisit.
151
151
 
152
152
  **Verify after a plugin update:**
153
153
 
154
- 1. Visit `/admin/plugins/aexeo-seogeo/findings` and click **Refresh**.
154
+ 1. Visit `/admin/plugins/aexeo-emdash/findings` and click **Refresh**.
155
155
  Toast should show non-zero rules sweeping. (A zero count *can*
156
156
  be valid for a clean site, but if you previously had findings
157
157
  and now have none, suspect the upgrade.)
@@ -216,7 +216,7 @@ Treat anything outside that range as best-effort.
216
216
 
217
217
  ## Removing
218
218
 
219
- Delete the dependency, the import, and the `seogeoPlugin()` line in
219
+ Delete the dependency, the import, and the `aexeoPlugin()` line in
220
220
  `integrations:[emdash({plugins:[...]})]`. The KV keys the plugin
221
221
  wrote remain in your KV namespace — purge with
222
222
  `wrangler kv:key delete --prefix=findings:` and
@@ -243,26 +243,26 @@ Trade-offs vs. configured mode:
243
243
  ```js
244
244
  // astro.config.mjs (sandboxed mode)
245
245
  import { sandbox } from "@emdash-cms/cloudflare";
246
- import { seogeoPluginSandboxed } from "@aeptus/aexeo-emdash";
246
+ import { aexeoPluginSandboxed } from "@aeptus/aexeo-emdash";
247
247
 
248
248
  emdash({
249
249
  database: d1({ binding: "DB" }),
250
250
  storage: r2({ binding: "MEDIA" }),
251
251
  sandboxed: [
252
- seogeoPluginSandboxed({
252
+ aexeoPluginSandboxed({
253
253
  // Public host of the deployed sidecar Worker.
254
- evaluatorHost: "seogeo-crawl-worker.<subdomain>.workers.dev",
254
+ evaluatorHost: "aexeo-crawl-worker.<subdomain>.workers.dev",
255
255
  }),
256
256
  ],
257
257
  sandboxRunner: sandbox(),
258
258
  });
259
259
  ```
260
260
 
261
- The sidecar Worker template lives at `packages/seogeo-crawl-worker/`
261
+ The sidecar Worker template lives at `packages/aexeo-crawl-worker/`
262
262
  in this repo. Per-site deploy:
263
263
 
264
264
  ```bash
265
- cd seogeo-crawl-worker
265
+ cd aexeo-crawl-worker
266
266
  # Edit wrangler.toml: name, R2 bucket name, SITE_URL
267
267
  npx wrangler login
268
268
  npx wrangler r2 bucket create <bucket-name>
@@ -271,7 +271,7 @@ echo "$(openssl rand -hex 32)" | npx wrangler secret put EVAL_TOKEN
271
271
  ```
272
272
 
273
273
  Then in the admin UI, visit
274
- `/admin/plugins/aexeo-seogeo/setup` and paste the deployed URL +
274
+ `/admin/plugins/aexeo-emdash/setup` and paste the deployed URL +
275
275
  the same token.
276
276
 
277
277
  ## Alternative install sources
@@ -316,7 +316,7 @@ present, double-check the package version is recent (≥ the version
316
316
  that switched to direct .wasm imports — see git log for `Switch
317
317
  configured-mode WASM from inlined bytes to direct .wasm import`).
318
318
 
319
- **`seogeo: WASM module did not resolve to a WebAssembly.Module`**
319
+ **`aexeo: WASM module did not resolve to a WebAssembly.Module`**
320
320
  The bundler resolved the .wasm import but produced something other
321
321
  than a Module (URL string, Uint8Array). Same fix as above: ensure
322
322
  `vite-plugin-wasm` is loaded.
@@ -327,7 +327,7 @@ sandboxed two-arg ctx shape. Update; it's fixed in the version with
327
327
  `Switch configured-mode WASM from inlined bytes to direct .wasm
328
328
  import` in the commit log.
329
329
 
330
- **`/admin/plugins` doesn't list seogeo, but `/findings` works.** The
330
+ **`/admin/plugins` doesn't list Aexeo, but `/findings` works.** The
331
331
  emdash version's plugins meta page may filter out plugins without a
332
332
  `/` adminPage entry. The package declares one explicitly; if you see
333
333
  this on a recent version, it's an emdash regression — file upstream.
@@ -344,7 +344,7 @@ Node adapter.
344
344
 
345
345
  ## What the plugin actually does
346
346
 
347
- - **Findings page** (`/_emdash/admin/plugins/aexeo-seogeo/findings`):
347
+ - **Findings page** (`/_emdash/admin/plugins/aexeo-emdash/findings`):
348
348
  Block Kit table of every rule violation across the site. Filter by
349
349
  severity. Click a route in the picker to drill into per-document
350
350
  findings.
@@ -371,6 +371,6 @@ inline. Findings are stored in the host's plugin KV (the
371
371
  `PluginContext.kv` accessor). The Refresh button does the same thing
372
372
  but for every document in every configured collection. The WASM
373
373
  itself is the same `aexeo-emdash-bridge` Rust crate that powers the
374
- seogeo CLI; it's compiled to WebAssembly via wasm-pack and imported
374
+ Aexeo CLI; it's compiled to WebAssembly via wasm-pack and imported
375
375
  by the host's bundler (Vite + `vite-plugin-wasm`). No separate
376
376
  service, no sidecar, no auth token.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Aexeo
3
+ Copyright (c) 2026 Aeptus
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @aeptus/aexeo-emdash
2
2
 
3
- Aexeo's seogeo SEO/GEO content evaluator as an emdash plugin.
3
+ Aexeo SEO/GEO content evaluator as an emdash plugin.
4
4
 
5
5
  Adds a Findings admin page, per-document panel, and dashboard
6
6
  intelligence-score widget to an emdash site. Saves auto-evaluate the
@@ -14,7 +14,7 @@ npm install @aeptus/aexeo-emdash vite-plugin-wasm
14
14
 
15
15
  ```js
16
16
  // astro.config.mjs
17
- import { seogeoPlugin } from "@aeptus/aexeo-emdash";
17
+ import { aexeoPlugin } from "@aeptus/aexeo-emdash";
18
18
  import wasm from "vite-plugin-wasm";
19
19
 
20
20
  export default defineConfig({
@@ -26,7 +26,7 @@ export default defineConfig({
26
26
  emdash({
27
27
  database: d1({ binding: "DB" }),
28
28
  storage: r2({ binding: "MEDIA" }),
29
- plugins: [seogeoPlugin()],
29
+ plugins: [aexeoPlugin()],
30
30
  }),
31
31
  ],
32
32
  });
@@ -40,7 +40,7 @@ troubleshooting list, see [INSTALL.md](./INSTALL.md).
40
40
 
41
41
  ## What it does
42
42
 
43
- - **Findings page** at `/_emdash/admin/plugins/aexeo-seogeo/findings`:
43
+ - **Findings page** at `/_emdash/admin/plugins/aexeo-emdash/findings`:
44
44
  rule violations across the site, filterable by severity.
45
45
  - **Document panel** at `/document`: findings scoped to one document.
46
46
  - **Dashboard widget**: top-line intelligence score (citation, truth,
@@ -59,13 +59,108 @@ troubleshooting list, see [INSTALL.md](./INSTALL.md).
59
59
  bundler handles compilation at build time. `vite-plugin-wasm` is a
60
60
  hard requirement on the consumer side.
61
61
 
62
+ ## Configuring collections
63
+
64
+ The plugin sweeps `["posts", "pages"]` by default — the slugs the
65
+ `@emdash-cms/template-blog-cloudflare` template ships with. Three knobs
66
+ to override, in precedence order:
67
+
68
+ ```js
69
+ // Full override — replace the default entirely.
70
+ // Use when your schema has none of the default slugs.
71
+ aexeoPlugin({ collections: ["blog_posts", "pages"] })
72
+
73
+ // Extend the default — add slugs alongside posts + pages.
74
+ aexeoPlugin({ includeCollections: ["guides", "faqs"] })
75
+
76
+ // Subtract from the default — remove a slug.
77
+ aexeoPlugin({ excludeCollections: ["posts"] })
78
+
79
+ // Combine include + exclude (subtract first, then add).
80
+ // `collections` ignores both — it's the explicit-list override.
81
+ aexeoPlugin({
82
+ excludeCollections: ["posts"],
83
+ includeCollections: ["blog_posts", "guides"],
84
+ })
85
+ ```
86
+
87
+ Pointing any of these at a slug that doesn't exist is non-fatal:
88
+ the bridge's `content.list` returns empty and the missing collection
89
+ shows up in the Refresh summary's `errors` field.
90
+
91
+ ## Suppressing findings
92
+
93
+ When a finding is intentional (legal pages with non-standard SEO,
94
+ localized routes where a rule doesn't apply, draft documents whose
95
+ findings shouldn't surface yet), silence it with a suppression rule.
96
+ Suppressions are applied **before** findings are persisted to KV —
97
+ suppressed findings never reach the dashboard, `/findings`, or the
98
+ per-document panel.
99
+
100
+ ```js
101
+ aexeoPlugin({
102
+ suppressions: [
103
+ // route + rule
104
+ { routePattern: "/privacy", ruleIds: ["RULE001"] },
105
+
106
+ // recursive route subtree
107
+ { routePattern: "/fr-fr/**", ruleIds: ["RULE002"] },
108
+
109
+ // applies to every route
110
+ { ruleIds: ["RULE999"] },
111
+
112
+ // by collection
113
+ { collections: ["drafts"], ruleIds: ["RULE042"] },
114
+
115
+ // by document status
116
+ { statuses: ["draft"] }, // silence ALL findings on drafts
117
+ ],
118
+ })
119
+ ```
120
+
121
+ ### Glob syntax for `routePattern`
122
+
123
+ | Pattern | Matches |
124
+ |---|---|
125
+ | `*` | any chars **except** `/` |
126
+ | `**` | any chars **including** `/` (recursive) |
127
+ | `?` | exactly one char except `/` |
128
+
129
+ Patterns are anchored. `/about` matches only `/about`, not
130
+ `/about/team` — use `/about/**` if you want a subtree.
131
+
132
+ > **Migrating from a local patch**: if your previous setup used
133
+ > looser patterns (e.g. one-asterisk-means-everything), update them
134
+ > on bump. `*` is intentionally single-segment so editors can scope
135
+ > rules to a level of the path hierarchy without recursive surprises.
136
+
137
+ ### Selector semantics
138
+
139
+ A rule may set any combination of `routePattern`, `ruleIds`,
140
+ `collections`, and `statuses`. Matching is **AND across selectors,
141
+ OR across rules**: a finding is suppressed when at least one rule
142
+ matches it; a rule matches when every selector it sets matches the
143
+ finding's context.
144
+
145
+ Empty rules (`{}` with no selectors) are rejected at plugin
146
+ construction. That's a kill-switch for all findings everywhere
147
+ and almost certainly an editor mistake.
148
+
149
+ `collections` and `statuses` only meaningful for per-document
150
+ findings. Sitewide findings (cross-document audit issues) are
151
+ matched only by `routePattern` and `ruleIds`.
152
+
153
+ Suppressions are plugin-only by design. The CLI's `check` is the
154
+ canonical strict audit; if you want to silence findings at the CLI
155
+ layer, use `aexeo.toml`'s `[ignore]` block instead.
156
+
62
157
  ## Two factories
63
158
 
64
159
  The package exports two factories for different trust contexts:
65
160
 
66
- - `seogeoPlugin()` — **configured mode** (recommended). In-process
161
+ - `aexeoPlugin()` — **configured mode** (recommended). In-process
67
162
  plugin. Use for first-party emdash sites.
68
- - `seogeoPluginSandboxed({ evaluatorHost })` — **sandboxed mode**.
163
+ - `aexeoPluginSandboxed({ evaluatorHost })` — **sandboxed mode**.
69
164
  Requires a separately-deployed sidecar Worker. Use only when
70
165
  shipping to third-party emdash sites that shouldn't trust the
71
166
  plugin code with full host access.
package/dist/admin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/admin/Facts.tsx
2
2
  import { useCallback, useEffect, useState } from "react";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
- var PLUGIN_ID = "aexeo-seogeo";
4
+ var PLUGIN_ID = "aexeo-emdash";
5
5
  var API_BASE = "/_emdash/api";
6
6
  function Facts() {
7
7
  const [data, setData] = useState(null);
@@ -275,7 +275,7 @@ async function callRoute(kind, extra) {
275
275
  // src/admin/Findings.tsx
276
276
  import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
277
277
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
278
- var PLUGIN_ID2 = "aexeo-seogeo";
278
+ var PLUGIN_ID2 = "aexeo-emdash";
279
279
  var API_BASE2 = "/_emdash/api";
280
280
  function Findings() {
281
281
  const [state, setState] = useState2({
@@ -1,12 +1,20 @@
1
1
  import type { Suppression } from "./suppressions.js";
2
2
  export interface ConfiguredPluginOptions {
3
3
  /**
4
- * emdash collections the Refresh button sweeps. Comes through from
5
- * the descriptor's `options` field — see `seogeoPlugin({ collections })`
6
- * in src/index.ts. When undefined, falls back to DEFAULT_COLLECTIONS
7
- * (`["posts", "pages"]`).
4
+ * Full override of the swept collections. See `aexeoPlugin` in
5
+ * src/index.ts for the full precedence story.
8
6
  */
9
7
  collections?: readonly string[];
8
+ /**
9
+ * Add to the default `["posts", "pages"]`. Ignored when
10
+ * `collections` is set.
11
+ */
12
+ includeCollections?: readonly string[];
13
+ /**
14
+ * Remove from the default `["posts", "pages"]`. Applied before
15
+ * `includeCollections`. Ignored when `collections` is set.
16
+ */
17
+ excludeCollections?: readonly string[];
10
18
  /**
11
19
  * Editor-workflow suppressions. See `Suppression` in suppressions.ts
12
20
  * for the rule shape and matching semantics. Compiled once at plugin
@@ -1 +1 @@
1
- {"version":3,"file":"configured.d.ts","sourceRoot":"","sources":["../src/configured.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAoDrD,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CA+F3E;AAID,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"configured.d.ts","sourceRoot":"","sources":["../src/configured.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmFrD,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAyG3E;AAID,eAAe,YAAY,CAAC"}
@@ -89,7 +89,14 @@ async function handleAfterSaveConfigured(event, ctx, evaluator, suppressionFilte
89
89
  const pageFindings = result.findings.filter(
90
90
  (finding) => finding.scope === "page"
91
91
  );
92
- const filtered = suppressionFilter === void 0 ? pageFindings : suppressionFilter.apply(document.route, pageFindings);
92
+ const filtered = suppressionFilter === void 0 ? pageFindings : suppressionFilter.apply(
93
+ {
94
+ route: document.route,
95
+ collection: adapted.meta.collection,
96
+ status: adapted.meta.status
97
+ },
98
+ pageFindings
99
+ );
93
100
  await kv.set(findingsKey(document.route), {
94
101
  route: document.route,
95
102
  findings: filtered
@@ -140,7 +147,7 @@ async function evaluateAndPersistAll(ctx, options) {
140
147
  }
141
148
  const result = await options.evaluator(documents);
142
149
  if (!result.ok) {
143
- log?.error?.(`seogeo evaluator failure (${result.reason})`, {
150
+ log?.error?.(`aexeo evaluator failure (${result.reason})`, {
144
151
  detail: result.detail
145
152
  });
146
153
  summary.errors.push(`${result.reason}: ${result.detail}`);
@@ -158,7 +165,13 @@ async function evaluateAndPersistAll(ctx, options) {
158
165
  }
159
166
  let totalAfterSuppression = 0;
160
167
  for (const [route, findings] of findingsByRoute) {
161
- const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(route, findings);
168
+ const stored = adaptedByRoute.get(route);
169
+ const context = {
170
+ route,
171
+ ...stored?.meta.collection === void 0 ? {} : { collection: stored.meta.collection },
172
+ ...stored?.meta.status === void 0 ? {} : { status: stored.meta.status }
173
+ };
174
+ const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(context, findings);
162
175
  await kv.set(findingsKey(route), { route, findings: filtered });
163
176
  summary.routesUpdated += 1;
164
177
  totalAfterSuppression += filtered.length;
@@ -418,7 +431,7 @@ function ensureInitialized() {
418
431
  }
419
432
  if (!(bridgeModule instanceof WebAssembly.Module)) {
420
433
  throw new Error(
421
- "seogeo: WASM module did not resolve to a WebAssembly.Module \u2014 the consumer's bundler isn't configured for .wasm imports. Add the .wasm loader to your Vite/wrangler config; see @aeptus/aexeo-emdash INSTALL.md for the recipe."
434
+ "aexeo: WASM module did not resolve to a WebAssembly.Module \u2014 the consumer's bundler isn't configured for .wasm imports. Add the .wasm loader to your Vite/wrangler config; see @aeptus/aexeo-emdash INSTALL.md for the recipe."
422
435
  );
423
436
  }
424
437
  const instance = new WebAssembly.Instance(bridgeModule, {
@@ -732,7 +745,7 @@ async function handleSave(ctx, body) {
732
745
 
733
746
  // src/suppressions.ts
734
747
  var NOOP_FILTER = {
735
- apply: (_route, findings) => [...findings]
748
+ apply: (_context, findings) => [...findings]
736
749
  };
737
750
  function compileSuppressions(rules) {
738
751
  if (rules === void 0 || rules.length === 0) {
@@ -741,25 +754,41 @@ function compileSuppressions(rules) {
741
754
  rules.forEach((rule, index) => {
742
755
  const hasRoute = rule.routePattern !== void 0 && rule.routePattern.length > 0;
743
756
  const hasRuleIds = rule.ruleIds !== void 0 && rule.ruleIds.length > 0;
744
- if (!hasRoute && !hasRuleIds) {
757
+ const hasCollections = rule.collections !== void 0 && rule.collections.length > 0;
758
+ const hasStatuses = rule.statuses !== void 0 && rule.statuses.length > 0;
759
+ if (!hasRoute && !hasRuleIds && !hasCollections && !hasStatuses) {
745
760
  throw new Error(
746
- `seogeoPlugin: suppressions[${index}] is empty \u2014 set routePattern, ruleIds, or both`
761
+ `aexeoPlugin: suppressions[${index}] is empty \u2014 set at least one of routePattern, ruleIds, collections, statuses`
747
762
  );
748
763
  }
749
764
  });
750
765
  const compiled = rules.map((rule) => ({
751
766
  matchRoute: rule.routePattern === void 0 ? matchAlways : globToMatcher(rule.routePattern),
752
- ruleIds: rule.ruleIds === void 0 || rule.ruleIds.length === 0 ? null : new Set(rule.ruleIds)
767
+ ruleIds: rule.ruleIds === void 0 || rule.ruleIds.length === 0 ? null : new Set(rule.ruleIds),
768
+ collections: rule.collections === void 0 || rule.collections.length === 0 ? null : new Set(rule.collections),
769
+ statuses: rule.statuses === void 0 || rule.statuses.length === 0 ? null : new Set(rule.statuses)
753
770
  }));
754
771
  return {
755
- apply(route, findings) {
756
- return findings.filter((finding) => !compiled.some((rule) => {
757
- if (!rule.matchRoute(route)) return false;
758
- if (rule.ruleIds !== null && !rule.ruleIds.has(finding.rule_id)) {
759
- return false;
760
- }
761
- return true;
762
- }));
772
+ apply(context, findings) {
773
+ return findings.filter(
774
+ (finding) => !compiled.some((rule) => {
775
+ if (!rule.matchRoute(context.route)) return false;
776
+ if (rule.ruleIds !== null && !rule.ruleIds.has(finding.rule_id)) {
777
+ return false;
778
+ }
779
+ if (rule.collections !== null) {
780
+ if (context.collection === void 0 || !rule.collections.has(context.collection)) {
781
+ return false;
782
+ }
783
+ }
784
+ if (rule.statuses !== null) {
785
+ if (context.status === void 0 || !rule.statuses.has(context.status)) {
786
+ return false;
787
+ }
788
+ }
789
+ return true;
790
+ })
791
+ );
763
792
  }
764
793
  };
765
794
  }
@@ -767,16 +796,35 @@ var matchAlways = () => true;
767
796
  function globToMatcher(pattern) {
768
797
  const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
769
798
  const DOUBLE_STAR_TOKEN = "";
770
- let body = escaped.replace(/\*\*/g, DOUBLE_STAR_TOKEN).replace(/\*/g, "[^/]*").replace(new RegExp(DOUBLE_STAR_TOKEN, "g"), ".*").replace(/\?/g, "[^/]");
799
+ const body = escaped.replace(/\*\*/g, DOUBLE_STAR_TOKEN).replace(/\*/g, "[^/]*").replace(new RegExp(DOUBLE_STAR_TOKEN, "g"), ".*").replace(/\?/g, "[^/]");
771
800
  const re = new RegExp(`^${body}$`);
772
801
  return (route) => re.test(route);
773
802
  }
774
803
 
775
804
  // src/version.ts
776
- var PACKAGE_VERSION = "0.4.0";
805
+ var PACKAGE_VERSION = "0.5.0";
777
806
 
778
807
  // src/configured.ts
779
808
  import { definePlugin } from "emdash";
809
+ function resolveCollections(explicit, include, exclude) {
810
+ if (explicit !== void 0) {
811
+ return [...explicit];
812
+ }
813
+ const excludeSet = new Set(exclude ?? []);
814
+ const base = DEFAULT_COLLECTIONS.filter(
815
+ (slug) => !excludeSet.has(slug)
816
+ );
817
+ if (include === void 0 || include.length === 0) {
818
+ return base;
819
+ }
820
+ const result = [...base];
821
+ for (const slug of include) {
822
+ if (!result.includes(slug)) {
823
+ result.push(slug);
824
+ }
825
+ }
826
+ return result;
827
+ }
780
828
  var inProcessEvaluator = async (documents) => {
781
829
  try {
782
830
  const raw = await evaluateDocuments2(JSON.stringify(documents));
@@ -795,10 +843,14 @@ var inProcessEvaluator = async (documents) => {
795
843
  }
796
844
  };
797
845
  function createPlugin(options = {}) {
798
- const collections = options.collections === void 0 ? DEFAULT_COLLECTIONS : [...options.collections];
846
+ const collections = resolveCollections(
847
+ options.collections,
848
+ options.includeCollections,
849
+ options.excludeCollections
850
+ );
799
851
  const suppressionFilter = compileSuppressions(options.suppressions);
800
852
  return definePlugin({
801
- id: "aexeo-seogeo",
853
+ id: "aexeo-emdash",
802
854
  version: PACKAGE_VERSION,
803
855
  capabilities: ["read:content"],
804
856
  hooks: {
@@ -820,8 +872,8 @@ function createPlugin(options = {}) {
820
872
  handler: (ctx) => handleAdminRoute(ctx, collections)
821
873
  },
822
874
  // JSON data endpoint for the React adminEntry. Two routes:
823
- // POST /_emdash/api/plugins/aexeo-seogeo/data — read current findings
824
- // POST /_emdash/api/plugins/aexeo-seogeo/refresh — sweep + read
875
+ // POST /_emdash/api/plugins/aexeo-emdash/data — read current findings
876
+ // POST /_emdash/api/plugins/aexeo-emdash/refresh — sweep + read
825
877
  // Returning JSON (not Block Kit blocks) lets the React
826
878
  // <Findings/> component render proper <a href> links to the
827
879
  // emdash edit page and the public site, which Block Kit can't
@@ -862,7 +914,7 @@ function createPlugin(options = {}) {
862
914
  { path: "/facts", label: "Truth manifest" }
863
915
  ],
864
916
  widgets: [
865
- { id: "seogeo-score", size: "third", title: "SEO score" }
917
+ { id: "aexeo-score", size: "third", title: "SEO score" }
866
918
  ]
867
919
  }
868
920
  });
@@ -901,7 +953,7 @@ async function handlePageLoad(ctx, page) {
901
953
  if (normalized === "" || normalized === "findings") {
902
954
  return renderFindingsPage(ctx);
903
955
  }
904
- if (normalized === "widget:seogeo-score") {
956
+ if (normalized === "widget:aexeo-score") {
905
957
  return renderScoreWidget(ctx);
906
958
  }
907
959
  if (normalized === "document") {
@@ -1049,7 +1101,7 @@ async function renderScoreWidget(ctx) {
1049
1101
  { type: "header", text: "SEO score" },
1050
1102
  {
1051
1103
  type: "context",
1052
- text: "No documents indexed \u2014 click Refresh on the seogeo findings page."
1104
+ text: "No documents indexed \u2014 click Refresh on the Aexeo findings page."
1053
1105
  }
1054
1106
  ]
1055
1107
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { seogeoPluginSandboxed } from "./sandbox.js";
2
- export type { PluginAdminPage, PluginAdminWidget, SandboxedPluginDescriptor, SeogeoSandboxedOptions, } from "./sandbox.js";
1
+ export { aexeoPluginSandboxed } from "./sandbox.js";
2
+ export type { PluginAdminPage, PluginAdminWidget, SandboxedPluginDescriptor, AexeoSandboxedOptions, } from "./sandbox.js";
3
3
  export interface ConfiguredPluginDescriptor {
4
4
  id: string;
5
5
  version: string;
@@ -18,7 +18,7 @@ export interface ConfiguredPluginDescriptor {
18
18
  title?: string;
19
19
  }[];
20
20
  }
21
- export interface SeogeoPluginOptions {
21
+ export interface AexeoPluginOptions {
22
22
  /**
23
23
  * emdash collections the plugin sweeps when an admin clicks
24
24
  * Refresh on the findings page. Order doesn't matter; the sweep
@@ -29,24 +29,57 @@ export interface SeogeoPluginOptions {
29
29
  *
30
30
  * Defaults to `["posts", "pages"]` (the slugs the
31
31
  * `@emdash-cms/template-blog-cloudflare` template ships with).
32
- * Override when your schema uses different collection slugs:
32
+ * Three knobs, in precedence order:
33
33
  *
34
- * seogeoPlugin({ collections: ["posts", "guides", "products"] })
34
+ * - `collections` — full override. When set, replaces the
35
+ * default entirely. Use this when your schema has none of the
36
+ * default slugs (e.g. a site with `blog_posts` and `pages`).
35
37
  *
36
- * Pointing this at a slug that doesn't exist in your schema is
37
- * non-fatal: the bridge's `content.list` returns empty and the
38
- * sweep records the missing collection in the Refresh summary's
39
- * `errors` field. Safe to ship a superset for a project that may
40
- * add collections later.
38
+ * aexeoPlugin({ collections: ["blog_posts", "pages"] })
39
+ *
40
+ * - `includeCollections` — extend the default. Adds slugs to
41
+ * the existing default. Use this when your schema has the
42
+ * default slugs PLUS extras.
43
+ *
44
+ * aexeoPlugin({ includeCollections: ["guides", "faqs"] })
45
+ *
46
+ * - `excludeCollections` — subtract from the default. Removes
47
+ * slugs from the existing default. Use this when your schema
48
+ * has the defaults but you want to skip one.
49
+ *
50
+ * aexeoPlugin({ excludeCollections: ["posts"] })
51
+ *
52
+ * `includeCollections` and `excludeCollections` may be combined
53
+ * (subtract first, then add). `collections` ignores both — it's
54
+ * the explicit-list override.
55
+ *
56
+ * Pointing any of these at a slug that doesn't exist in your
57
+ * schema is non-fatal: the bridge's `content.list` returns empty
58
+ * and the sweep records the missing collection in the Refresh
59
+ * summary's `errors` field. Safe to ship a superset for a project
60
+ * that may add collections later.
41
61
  */
42
62
  collections?: readonly string[];
63
+ /**
64
+ * Slugs to add on top of the default `["posts", "pages"]`. Ignored
65
+ * when `collections` is set (which fully overrides the default).
66
+ * See `collections` for the full precedence story.
67
+ */
68
+ includeCollections?: readonly string[];
69
+ /**
70
+ * Slugs to remove from the default `["posts", "pages"]`. Applied
71
+ * before `includeCollections`, so adding a slug back via include
72
+ * is a no-op (it was never removed). Ignored when `collections`
73
+ * is set.
74
+ */
75
+ excludeCollections?: readonly string[];
43
76
  /**
44
77
  * Editor-workflow suppressions. Each rule silences findings that
45
78
  * match the route pattern (glob) AND/OR are in the rule-id set.
46
79
  * Applied before findings are persisted to KV — suppressed findings
47
80
  * never reach the dashboard, /findings, or the per-document panel.
48
81
  *
49
- * seogeoPlugin({
82
+ * aexeoPlugin({
50
83
  * suppressions: [
51
84
  * { routePattern: "/privacy", ruleIds: ["RULE001"] },
52
85
  * { routePattern: "/fr-fr/**", ruleIds: ["RULE002"] },
@@ -63,7 +96,7 @@ export interface SeogeoPluginOptions {
63
96
  *
64
97
  * Suppressions are plugin-only by design. The CLI's `check` is the
65
98
  * canonical strict audit; if you want to silence findings at the
66
- * CLI layer, use `seogeo.toml`'s `[ignore]` block instead. The two
99
+ * CLI layer, use `aexeo.toml`'s `[ignore]` block instead. The two
67
100
  * surfaces serve different audiences: the plugin is editorial
68
101
  * workflow, the CLI is build-gating.
69
102
  */
@@ -71,5 +104,5 @@ export interface SeogeoPluginOptions {
71
104
  }
72
105
  export type { Suppression } from "./suppressions.js";
73
106
  import type { Suppression } from "./suppressions.js";
74
- export declare function seogeoPlugin(options?: SeogeoPluginOptions): ConfiguredPluginDescriptor;
107
+ export declare function aexeoPlugin(options?: AexeoPluginOptions): ConfiguredPluginDescriptor;
75
108
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAYtB,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAOnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,YAAY,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACxE;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,0BAA0B,CAkD5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAYtB,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAOnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,YAAY,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACxE;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,WAAW,CACzB,OAAO,GAAE,kBAAuB,GAC/B,0BAA0B,CAqE5B"}
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ var baseCapabilities = [
6
6
  "write:artifacts:public/llms-full.txt",
7
7
  "write:artifacts:public/facts.json",
8
8
  "write:artifacts:public/*.md.txt",
9
- "kv:seogeo-baselines"
9
+ "kv:aexeo-baselines"
10
10
  ];
11
11
  function buildCapabilities(evaluatorHost) {
12
12
  if (evaluatorHost === null) {
@@ -23,13 +23,13 @@ function buildAllowedHosts(evaluatorHost) {
23
23
  }
24
24
 
25
25
  // src/version.ts
26
- var PACKAGE_VERSION = "0.4.0";
26
+ var PACKAGE_VERSION = "0.5.0";
27
27
 
28
28
  // src/sandbox.ts
29
- function seogeoPluginSandboxed(options = {}) {
30
- const evaluatorHost = options.evaluatorHost ?? process.env.SEOGEO_EVALUATOR_HOST ?? null;
29
+ function aexeoPluginSandboxed(options = {}) {
30
+ const evaluatorHost = options.evaluatorHost ?? process.env.AEXEO_EVALUATOR_HOST ?? null;
31
31
  return {
32
- id: "aexeo-seogeo",
32
+ id: "aexeo-emdash",
33
33
  version: PACKAGE_VERSION,
34
34
  // Subpath export of this same package; must match package.json
35
35
  // `exports["./sandbox"]`.
@@ -37,7 +37,7 @@ function seogeoPluginSandboxed(options = {}) {
37
37
  format: "standard",
38
38
  capabilities: buildCapabilities(evaluatorHost),
39
39
  allowedHosts: buildAllowedHosts(evaluatorHost),
40
- // Pages mount at /admin/plugins/aexeo-seogeo/<path>. The page name
40
+ // Pages mount at /admin/plugins/aexeo-emdash/<path>. The page name
41
41
  // (without leading slash) is what the sandbox entry receives in
42
42
  // `body.page` when emdash POSTs the page_load interaction.
43
43
  adminPages: [
@@ -46,15 +46,15 @@ function seogeoPluginSandboxed(options = {}) {
46
46
  { path: "/setup", label: "Setup" }
47
47
  ],
48
48
  adminWidgets: [
49
- { id: "seogeo-score", size: "third", title: "SEO score" }
49
+ { id: "aexeo-score", size: "third", title: "SEO score" }
50
50
  ]
51
51
  };
52
52
  }
53
53
 
54
54
  // src/index.ts
55
- function seogeoPlugin(options = {}) {
55
+ function aexeoPlugin(options = {}) {
56
56
  return {
57
- id: "aexeo-seogeo",
57
+ id: "aexeo-emdash",
58
58
  version: PACKAGE_VERSION,
59
59
  // Subpath import resolved by the consumer's bundler at build
60
60
  // time — must match the package.json `exports["./configured"]`
@@ -76,12 +76,21 @@ function seogeoPlugin(options = {}) {
76
76
  // the structured-clone semantics of that codegen.
77
77
  options: {
78
78
  ...options.collections === void 0 ? {} : { collections: [...options.collections] },
79
- ...options.suppressions === void 0 ? {} : { suppressions: options.suppressions.map((rule) => ({ ...rule })) }
79
+ ...options.includeCollections === void 0 ? {} : { includeCollections: [...options.includeCollections] },
80
+ ...options.excludeCollections === void 0 ? {} : { excludeCollections: [...options.excludeCollections] },
81
+ ...options.suppressions === void 0 ? {} : {
82
+ suppressions: options.suppressions.map((rule) => ({
83
+ ...rule,
84
+ ...rule.ruleIds === void 0 ? {} : { ruleIds: [...rule.ruleIds] },
85
+ ...rule.collections === void 0 ? {} : { collections: [...rule.collections] },
86
+ ...rule.statuses === void 0 ? {} : { statuses: [...rule.statuses] }
87
+ }))
88
+ }
80
89
  },
81
90
  capabilities: [
82
91
  "read:content",
83
92
  "read:schema",
84
- "kv:seogeo-baselines"
93
+ "kv:aexeo-baselines"
85
94
  ],
86
95
  // adminPages drives the admin sidebar — one nav entry per item.
87
96
  // Don't list "/" alongside "/findings": both would render as
@@ -95,11 +104,11 @@ function seogeoPlugin(options = {}) {
95
104
  { path: "/document", label: "Document SEO" }
96
105
  ],
97
106
  adminWidgets: [
98
- { id: "seogeo-score", size: "third", title: "SEO score" }
107
+ { id: "aexeo-score", size: "third", title: "SEO score" }
99
108
  ]
100
109
  };
101
110
  }
102
111
  export {
103
- seogeoPlugin,
104
- seogeoPluginSandboxed
112
+ aexeoPlugin,
113
+ aexeoPluginSandboxed
105
114
  };
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EAGvB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAOhD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAqCD,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,SAAS,MAAM,EAAE,CAKnB;AASD,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,SAAS,MAAM,EAAE,CAMnB;AAKD,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAAqB,CAAC;AAWhE,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,CAAC,CAAC;CACV;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CAC3D;AAcD,eAAO,MAAM,cAAc,yBAAyB,CAAC;AACrD,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,WAAW,GACd,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAUtC;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AAOD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CACF,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACzC,OAAO,CAAC,WAAW,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,WAAW,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,iBAAiB,CAAC;IAK3B,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,GAAG,CAAC,EAAE;QACJ,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QACxC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QACxC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;KAC1C,CAAC;CACH;AAOD,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AA0BD,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,IAAI,CAAC,CAEf;AAYD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,qBAAqB,EAC5B,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,WAAW,EACtB,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAAC,IAAI,CAAC,CAoCf;AAMD,eAAO,MAAM,mBAAmB,6BAA8B,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAKD,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAelD,MAAM,MAAM,WAAW,GAAG,CACxB,SAAS,EAAE,SAAS,cAAc,EAAE,KACjC,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAWhC,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;IACP,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,SAAS,EAAE,WAAW,CAAC;IACvB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,GACA,OAAO,CAAC,cAAc,CAAC,CAiGzB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAOD,eAAO,MAAM,SAAS,kBAAkB,CAAC;AAMzC,wBAAsB,eAAe,CACnC,EAAE,EAAE,WAAW,GACd,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAGzB;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,WAAW,GACd,OAAO,CAAC,cAAc,EAAE,CAAC,CAE3B;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,WAAW,GACd,OAAO,CAAC,cAAc,EAAE,CAAC,CA+B3B;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,EAAE,CAAC,CAMpB"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -131,7 +131,7 @@ async function evaluateAndPersistAll(ctx, options) {
131
131
  }
132
132
  const result = await options.evaluator(documents);
133
133
  if (!result.ok) {
134
- log?.error?.(`seogeo evaluator failure (${result.reason})`, {
134
+ log?.error?.(`aexeo evaluator failure (${result.reason})`, {
135
135
  detail: result.detail
136
136
  });
137
137
  summary.errors.push(`${result.reason}: ${result.detail}`);
@@ -149,7 +149,13 @@ async function evaluateAndPersistAll(ctx, options) {
149
149
  }
150
150
  let totalAfterSuppression = 0;
151
151
  for (const [route, findings] of findingsByRoute2) {
152
- const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(route, findings);
152
+ const stored = adaptedByRoute.get(route);
153
+ const context = {
154
+ route,
155
+ ...stored?.meta.collection === void 0 ? {} : { collection: stored.meta.collection },
156
+ ...stored?.meta.status === void 0 ? {} : { status: stored.meta.status }
157
+ };
158
+ const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(context, findings);
153
159
  await kv.set(findingsKey(route), { route, findings: filtered });
154
160
  summary.routesUpdated += 1;
155
161
  totalAfterSuppression += filtered.length;
@@ -364,8 +370,8 @@ function failure(reason, rejected) {
364
370
 
365
371
  // src/mcp.ts
366
372
  var checkTool = {
367
- name: "seogeo.check",
368
- description: "Evaluate a list of EmdashDocument values against the seogeo rule engine and return the stable Finding contract. Mirrors the CLI's `seogeo-cli check` surface so agents, the admin UI, and the CI gate all see the same rule ids.",
373
+ name: "aexeo.check",
374
+ description: "Evaluate a list of EmdashDocument values against the Aexeo rule engine and return the stable Finding contract. Mirrors the CLI's `aexeo-cli check` surface so agents, the admin UI, and the CI gate all see the same rule ids.",
369
375
  inputSchema: {
370
376
  type: "object",
371
377
  properties: {
@@ -375,7 +381,7 @@ var checkTool = {
375
381
  },
376
382
  configJson: {
377
383
  type: "string",
378
- description: "Optional JSON-serialized seogeo Config. When absent the evaluator uses Config::default(), matching a cold CLI run."
384
+ description: "Optional JSON-serialized Aexeo config. When absent the evaluator uses Config::default(), matching a cold CLI run."
379
385
  }
380
386
  },
381
387
  required: ["documents"]
@@ -402,8 +408,8 @@ var checkTool = {
402
408
  }
403
409
  };
404
410
  var indexNowSubmitTool = {
405
- name: "seogeo.indexnow.submit",
406
- description: "Submit a list of URLs to the IndexNow freshness endpoint. Mirrors the seogeo-cli `indexnow submit` contract: the IndexNow protocol requires every submitted URL to belong to the configured site host. URLs that do not match the host are returned in `rejected` and never sent over the wire.",
411
+ name: "aexeo.indexnow.submit",
412
+ description: "Submit a list of URLs to the IndexNow freshness endpoint. Mirrors the aexeo-cli `indexnow submit` contract: the IndexNow protocol requires every submitted URL to belong to the configured site host. URLs that do not match the host are returned in `rejected` and never sent over the wire.",
407
413
  inputSchema: {
408
414
  type: "object",
409
415
  properties: {
@@ -435,7 +441,7 @@ function definePlugin(plugin) {
435
441
  }
436
442
  async function handleAdminRoute(input, ctx) {
437
443
  ctx.log?.info?.(
438
- `seogeo route: type=${input.input?.type} page=${input.input?.page ?? ""}`
444
+ `aexeo route: type=${input.input?.type} page=${input.input?.page ?? ""}`
439
445
  );
440
446
  const dispatch = { body: input.input, kv: ctx.kv, ctx };
441
447
  if (dispatch.body.type === "page_load") {
@@ -474,7 +480,7 @@ async function handlePageLoad(ctx, page) {
474
480
  if (normalized === "findings") {
475
481
  return renderFindingsPage(ctx);
476
482
  }
477
- if (normalized === "widget:seogeo-score") {
483
+ if (normalized === "widget:aexeo-score") {
478
484
  return renderScoreWidget(ctx);
479
485
  }
480
486
  if (normalized === "document") {
@@ -504,7 +510,7 @@ async function handleRefresh(ctx) {
504
510
  return {
505
511
  ok: false,
506
512
  reason: "config_missing",
507
- detail: "sidecar not configured \u2014 open the seogeo Setup page and enter your evaluator URL and token"
513
+ detail: "sidecar not configured \u2014 open the Aexeo Setup page and enter your evaluator URL and token"
508
514
  };
509
515
  }
510
516
  return evaluateViaSidecar(
@@ -763,10 +769,10 @@ function documentFindingsTable(findings) {
763
769
  async function renderSetupPage(ctx, options = {}) {
764
770
  const existing = await readSidecarConfig(ctx.kv);
765
771
  const blocks = [
766
- { type: "header", text: "seogeo setup" },
772
+ { type: "header", text: "Aexeo setup" },
767
773
  {
768
774
  type: "context",
769
- text: "Paste the URL and auth token of your deployed seogeo-crawl-worker. These are stored in plugin KV and read at runtime \u2014 no rebuild required after a change. Rotate the token here whenever you redeploy the sidecar with a new secret."
775
+ text: "Paste the URL and auth token of your deployed aexeo-crawl-worker. These are stored in plugin KV and read at runtime \u2014 no rebuild required after a change. Rotate the token here whenever you redeploy the sidecar with a new secret."
770
776
  }
771
777
  ];
772
778
  if (options.bannerError !== void 0) {
@@ -790,7 +796,7 @@ async function renderSetupPage(ctx, options = {}) {
790
796
  type: "text_input",
791
797
  action_id: "evaluator_url",
792
798
  label: "Sidecar URL",
793
- placeholder: "https://seogeo-crawl-worker.<subdomain>.workers.dev",
799
+ placeholder: "https://aexeo-crawl-worker.<subdomain>.workers.dev",
794
800
  initial_value: options.initialUrl ?? existing?.url ?? ""
795
801
  },
796
802
  {
package/dist/sandbox.d.ts CHANGED
@@ -18,8 +18,8 @@ export interface SandboxedPluginDescriptor {
18
18
  adminWidgets?: readonly PluginAdminWidget[];
19
19
  allowedHosts?: readonly string[];
20
20
  }
21
- export interface SeogeoSandboxedOptions {
21
+ export interface AexeoSandboxedOptions {
22
22
  evaluatorHost?: string;
23
23
  }
24
- export declare function seogeoPluginSandboxed(options?: SeogeoSandboxedOptions): SandboxedPluginDescriptor;
24
+ export declare function aexeoPluginSandboxed(options?: AexeoSandboxedOptions): SandboxedPluginDescriptor;
25
25
  //# sourceMappingURL=sandbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAGnB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAGxC,YAAY,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAeD,MAAM,WAAW,sBAAsB;IAgBrC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,sBAA2B,GACnC,yBAAyB,CAwB3B"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAGnB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAGxC,YAAY,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAeD,MAAM,WAAW,qBAAqB;IAgBpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,qBAA0B,GAClC,yBAAyB,CAwB3B"}
@@ -2,9 +2,16 @@ import type { Finding } from "./types.js";
2
2
  export interface Suppression {
3
3
  routePattern?: string;
4
4
  ruleIds?: readonly string[];
5
+ collections?: readonly string[];
6
+ statuses?: readonly string[];
7
+ }
8
+ export interface SuppressionContext {
9
+ route: string;
10
+ collection?: string;
11
+ status?: string;
5
12
  }
6
13
  export interface SuppressionFilter {
7
- apply(route: string, findings: readonly Finding[]): Finding[];
14
+ apply(context: SuppressionContext, findings: readonly Finding[]): Finding[];
8
15
  }
9
16
  export declare function compileSuppressions(rules: readonly Suppression[] | undefined): SuppressionFilter;
10
17
  //# sourceMappingURL=suppressions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"suppressions.d.ts","sourceRoot":"","sources":["../src/suppressions.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAkB1C,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;CAC/D;AASD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,GACxC,iBAAiB,CAoCnB"}
1
+ {"version":3,"file":"suppressions.d.ts","sourceRoot":"","sources":["../src/suppressions.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAsB1C,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAOD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,CACH,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,SAAS,OAAO,EAAE,GAC3B,OAAO,EAAE,CAAC;CACd;AASD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,GACxC,iBAAiB,CAyEnB"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "0.4.0";
1
+ export declare const PACKAGE_VERSION = "0.5.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@aeptus/aexeo-emdash",
3
- "version": "0.4.0",
4
- "description": "Aexeo seogeo SEO/GEO content evaluator as an emdash plugin",
3
+ "version": "0.5.0",
4
+ "description": "Aexeo SEO/GEO content evaluator as an emdash plugin",
5
5
  "license": "MIT",
6
- "author": "Aexeo",
6
+ "author": "Aeptus",
7
7
  "homepage": "https://github.com/schiste/Aexeo/tree/main/packages/aexeo-emdash",
8
8
  "repository": {
9
9
  "type": "git",
Binary file