slopbrick 0.18.5 → 0.18.7

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.cjs CHANGED
@@ -36,7 +36,7 @@ var VERSION;
36
36
  var init_header = __esm({
37
37
  "src/types/_header.ts"() {
38
38
  "use strict";
39
- VERSION = "0.18.5";
39
+ VERSION = "0.18.7";
40
40
  }
41
41
  });
42
42
 
@@ -29765,6 +29765,9 @@ var init_expired_code_example = __esm({
29765
29765
  const issues = [];
29766
29766
  const source = facts.v2?._source;
29767
29767
  if (!source) return issues;
29768
+ const packages = declaredPackages(context.cwd);
29769
+ const packageName = context.packageName;
29770
+ if (packageName) packages.add(packageName);
29768
29771
  const blocks = extractFencedCodeBlocks(source);
29769
29772
  for (const block of blocks) {
29770
29773
  if (!CODE_LANGS.has(block.lang)) continue;
@@ -29772,7 +29775,7 @@ var init_expired_code_example = __esm({
29772
29775
  const imports = extractImports(block.body);
29773
29776
  for (const imp of imports) {
29774
29777
  const pkgName = stripSubpath(imp);
29775
- if (context.packages.has(pkgName)) continue;
29778
+ if (packages.has(pkgName)) continue;
29776
29779
  issues.push({
29777
29780
  ruleId: "docs/expired-code-example",
29778
29781
  category: "docs",
@@ -29825,7 +29828,12 @@ function collectExports(cwd) {
29825
29828
  /\bexport\s+class\s+([A-Za-z_$][\w$]*)/g,
29826
29829
  /\bexport\s+interface\s+([A-Za-z_$][\w$]*)/g,
29827
29830
  /\bexport\s+type\s+([A-Za-z_$][\w$]*)/g,
29828
- /\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g
29831
+ /\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g,
29832
+ // v0.18.6: also collect field names from `export interface` and
29833
+ // `export type` declarations. Without this, fields like
29834
+ // `crossFileDrift`, `aiQuality`, `engineeringHygiene` are
29835
+ // flagged as stale even though they're valid type fields.
29836
+ /^\s*(?:readonly\s+)?([A-Za-z_$][\w$]*)\s*[?:]/gm
29829
29837
  ]) {
29830
29838
  let m;
29831
29839
  while ((m = re.exec(source)) !== null) {
@@ -29836,6 +29844,21 @@ function collectExports(cwd) {
29836
29844
  }
29837
29845
  return out;
29838
29846
  }
29847
+ function looksLikeProseLabel(inside) {
29848
+ const trimmed = inside.trim();
29849
+ if (trimmed.length === 0) return false;
29850
+ if (trimmed.startsWith("`") || trimmed.startsWith("/")) return true;
29851
+ if (trimmed.includes("`")) return true;
29852
+ if (/\d+\s+[a-z]/i.test(trimmed)) return true;
29853
+ const parts = trimmed.split(",").map((s) => s.trim());
29854
+ if (parts.length >= 3) {
29855
+ const allNumeric = parts.every((p) => /^\d+\.?\d*$/.test(p));
29856
+ if (!allNumeric) return true;
29857
+ }
29858
+ if (trimmed.length > 40 && !trimmed.includes(",")) return true;
29859
+ if (trimmed.includes("\u2014") || trimmed.includes("\u2013")) return true;
29860
+ return false;
29861
+ }
29839
29862
  var import_node_fs7, import_node_path7, RESERVED, SOURCE_EXTS, SOURCE_ROOTS, CAP, staleFunctionReferenceRule;
29840
29863
  var init_stale_function_reference = __esm({
29841
29864
  "src/rules/docs/stale-function-reference.ts"() {
@@ -29845,6 +29868,7 @@ var init_stale_function_reference = __esm({
29845
29868
  init_rule();
29846
29869
  init_doc_freshness();
29847
29870
  RESERVED = /* @__PURE__ */ new Set([
29871
+ // JS reserved words
29848
29872
  "true",
29849
29873
  "false",
29850
29874
  "null",
@@ -29944,7 +29968,472 @@ var init_stale_function_reference = __esm({
29944
29968
  "next",
29945
29969
  "vue",
29946
29970
  "angular",
29947
- "svelte"
29971
+ "svelte",
29972
+ // Framework / runtime names
29973
+ "html",
29974
+ "astro",
29975
+ "python",
29976
+ "jvm",
29977
+ "kotlin",
29978
+ "swift",
29979
+ "dart",
29980
+ "ruby",
29981
+ "rust",
29982
+ "cpp",
29983
+ "go",
29984
+ "java",
29985
+ "php",
29986
+ "php-html",
29987
+ "csharp",
29988
+ "typescript",
29989
+ "javascript",
29990
+ "jsx",
29991
+ "tsx",
29992
+ "mjs",
29993
+ "cjs",
29994
+ "esnext",
29995
+ "es6",
29996
+ "es2022",
29997
+ "es2023",
29998
+ "esm",
29999
+ "cjs",
30000
+ "umd",
30001
+ "amd",
30002
+ "commonjs",
30003
+ "require",
30004
+ "module",
30005
+ "exports",
30006
+ "define",
30007
+ "global",
30008
+ "window",
30009
+ "document",
30010
+ "process",
30011
+ "console",
30012
+ "buffer",
30013
+ "stream",
30014
+ "fetch",
30015
+ "axios",
30016
+ "express",
30017
+ "fastify",
30018
+ "koa",
30019
+ "hapi",
30020
+ "nextjs",
30021
+ "nuxt",
30022
+ "remix",
30023
+ "gatsby",
30024
+ "sveltekit",
30025
+ "solid",
30026
+ "preact",
30027
+ "qwik",
30028
+ "lit",
30029
+ "stencil",
30030
+ "marko",
30031
+ "alpine",
30032
+ "stimulus",
30033
+ "turbo",
30034
+ "hotwire",
30035
+ // Models / providers
30036
+ "gpt",
30037
+ "claude",
30038
+ "gpt-3",
30039
+ "gpt-3.5",
30040
+ "gpt-4",
30041
+ "gpt-oss",
30042
+ "haiku",
30043
+ "sonnet",
30044
+ "opus",
30045
+ "aider",
30046
+ "tabby",
30047
+ "copilot",
30048
+ "cursor",
30049
+ "windsurf",
30050
+ "devin",
30051
+ "claude-code",
30052
+ // LLM-detection lingo
30053
+ "heuristic",
30054
+ "heuristics",
30055
+ "calibrate",
30056
+ "calibration",
30057
+ "calibrator",
30058
+ "corpus",
30059
+ "baseline",
30060
+ "baselines",
30061
+ "corpus-baselines",
30062
+ "lift",
30063
+ "recall",
30064
+ "precision",
30065
+ "fpRate",
30066
+ "ratio",
30067
+ "verdict",
30068
+ "USEFUL",
30069
+ "NOISY",
30070
+ "INVERTED",
30071
+ "HYGIENE",
30072
+ "DORMANT",
30073
+ "OK",
30074
+ "aiSpecific",
30075
+ "defaultOff",
30076
+ // Common slop-audit verbs/nouns
30077
+ "commit",
30078
+ "push",
30079
+ "reset",
30080
+ "rebase",
30081
+ "merge",
30082
+ "cherry-pick",
30083
+ "revert",
30084
+ "scan",
30085
+ "parse",
30086
+ "build",
30087
+ "test",
30088
+ "lint",
30089
+ "format",
30090
+ "check",
30091
+ "audit",
30092
+ "fix",
30093
+ "patch",
30094
+ "diff",
30095
+ "pr",
30096
+ "ci",
30097
+ "cd",
30098
+ "gh",
30099
+ "npm",
30100
+ "npx",
30101
+ "pnpm",
30102
+ "yaml",
30103
+ "json",
30104
+ "toml",
30105
+ "csv",
30106
+ "md",
30107
+ "mdx",
30108
+ "sh",
30109
+ "bash",
30110
+ "zsh",
30111
+ "fish",
30112
+ "ascii",
30113
+ "utf8",
30114
+ "utf-8",
30115
+ "base64",
30116
+ "hex",
30117
+ "binary",
30118
+ "text",
30119
+ // Common design / ui terms
30120
+ "flex",
30121
+ "grid",
30122
+ "auto",
30123
+ "min",
30124
+ "max",
30125
+ "fill",
30126
+ "stretch",
30127
+ "wrap",
30128
+ "nowrap",
30129
+ "inline",
30130
+ "block",
30131
+ "hidden",
30132
+ "visible",
30133
+ "static",
30134
+ "fixed",
30135
+ "absolute",
30136
+ "relative",
30137
+ "sticky",
30138
+ "pointer",
30139
+ "cursor",
30140
+ "focus",
30141
+ "hover",
30142
+ "active",
30143
+ "disabled",
30144
+ "readonly",
30145
+ "primary",
30146
+ "secondary",
30147
+ "tertiary",
30148
+ "success",
30149
+ "warning",
30150
+ "danger",
30151
+ "info",
30152
+ "muted",
30153
+ "sm",
30154
+ "md",
30155
+ "lg",
30156
+ "xl",
30157
+ "xxl",
30158
+ "xs",
30159
+ "2xl",
30160
+ "3xl",
30161
+ "4xl",
30162
+ // Math / types
30163
+ "array",
30164
+ "map",
30165
+ "set",
30166
+ "weakmap",
30167
+ "weakset",
30168
+ "object",
30169
+ "string",
30170
+ "number",
30171
+ "boolean",
30172
+ "bigint",
30173
+ "symbol",
30174
+ "null",
30175
+ "undefined",
30176
+ "any",
30177
+ "unknown",
30178
+ "never",
30179
+ "void",
30180
+ "readonly",
30181
+ "private",
30182
+ "public",
30183
+ "protected",
30184
+ "static",
30185
+ "abstract",
30186
+ "async",
30187
+ "generator",
30188
+ "iterator",
30189
+ "iterable",
30190
+ "promise",
30191
+ "observable",
30192
+ // Auth / domain
30193
+ "admin",
30194
+ "user",
30195
+ "guest",
30196
+ "anonymous",
30197
+ "authenticated",
30198
+ "unauthenticated",
30199
+ "jwt",
30200
+ "oauth",
30201
+ "oidc",
30202
+ "saml",
30203
+ "csrf",
30204
+ "xss",
30205
+ "sql",
30206
+ "nosql",
30207
+ "orm",
30208
+ "prisma",
30209
+ "drizzle",
30210
+ "sequelize",
30211
+ "mongoose",
30212
+ "redis",
30213
+ "postgres",
30214
+ "mysql",
30215
+ "sqlite",
30216
+ "kafka",
30217
+ "rabbitmq",
30218
+ "graphql",
30219
+ "rest",
30220
+ "grpc",
30221
+ "websocket",
30222
+ // slop-audit specific
30223
+ "slopbrick",
30224
+ "usebrick",
30225
+ "deadcode",
30226
+ "unused",
30227
+ "orphan",
30228
+ "zombie",
30229
+ "blocker",
30230
+ "warning",
30231
+ "info",
30232
+ "error",
30233
+ "verbose",
30234
+ "debug",
30235
+ "silly",
30236
+ "p50",
30237
+ "p90",
30238
+ "p95",
30239
+ "p99",
30240
+ "min",
30241
+ "max",
30242
+ "avg",
30243
+ "mean",
30244
+ "median",
30245
+ "ratchet",
30246
+ "tier",
30247
+ "composite",
30248
+ "fitness",
30249
+ "fpr",
30250
+ "tpr",
30251
+ "roc",
30252
+ "should",
30253
+ "could",
30254
+ "would",
30255
+ "might",
30256
+ "must",
30257
+ "shall",
30258
+ "may",
30259
+ "can",
30260
+ "todo",
30261
+ "fixme",
30262
+ "xxx",
30263
+ "hack",
30264
+ "note",
30265
+ "warning",
30266
+ "attention",
30267
+ "h1",
30268
+ "h2",
30269
+ "h3",
30270
+ "h4",
30271
+ "h5",
30272
+ "h6",
30273
+ "strong",
30274
+ "em",
30275
+ "b",
30276
+ "i",
30277
+ "u",
30278
+ "true",
30279
+ "false",
30280
+ "yes",
30281
+ "no",
30282
+ "on",
30283
+ "off",
30284
+ "enable",
30285
+ "disable",
30286
+ "ltr",
30287
+ "rtl",
30288
+ "auto",
30289
+ "start",
30290
+ "end",
30291
+ "center",
30292
+ "baseline",
30293
+ "stretch",
30294
+ "rounded",
30295
+ "sharp",
30296
+ "outline",
30297
+ "ghost",
30298
+ "link",
30299
+ "filled",
30300
+ "row",
30301
+ "col",
30302
+ "gap",
30303
+ "pad",
30304
+ "margin",
30305
+ "padding",
30306
+ "border",
30307
+ "shadow",
30308
+ "transparent",
30309
+ "currentcolor",
30310
+ "inherit",
30311
+ "initial",
30312
+ "unset",
30313
+ "revert",
30314
+ "hover",
30315
+ "focus",
30316
+ "active",
30317
+ "disabled",
30318
+ "checked",
30319
+ "indeterminate",
30320
+ "open",
30321
+ "close",
30322
+ "expanded",
30323
+ "collapsed",
30324
+ "selected",
30325
+ "pressed",
30326
+ // Web/CSS
30327
+ "div",
30328
+ "span",
30329
+ "p",
30330
+ "a",
30331
+ "img",
30332
+ "ul",
30333
+ "ol",
30334
+ "li",
30335
+ "table",
30336
+ "tr",
30337
+ "td",
30338
+ "th",
30339
+ "thead",
30340
+ "tbody",
30341
+ "tfoot",
30342
+ "caption",
30343
+ "figure",
30344
+ "figcaption",
30345
+ "main",
30346
+ "section",
30347
+ "article",
30348
+ "aside",
30349
+ "header",
30350
+ "footer",
30351
+ "nav",
30352
+ "form",
30353
+ "input",
30354
+ "button",
30355
+ "select",
30356
+ "option",
30357
+ "textarea",
30358
+ "label",
30359
+ "fieldset",
30360
+ "legend",
30361
+ "details",
30362
+ "summary",
30363
+ "dialog",
30364
+ "menu",
30365
+ "menuitem",
30366
+ "template",
30367
+ "slot",
30368
+ "picture",
30369
+ "source",
30370
+ "track",
30371
+ "video",
30372
+ "audio",
30373
+ "canvas",
30374
+ "svg",
30375
+ "iframe",
30376
+ "embed",
30377
+ "object",
30378
+ "portal",
30379
+ // Common business terms
30380
+ "api",
30381
+ "cli",
30382
+ "ui",
30383
+ "ux",
30384
+ "sdk",
30385
+ "ide",
30386
+ "cli",
30387
+ "docs",
30388
+ "doc",
30389
+ "blog",
30390
+ "post",
30391
+ "page",
30392
+ "view",
30393
+ "tab",
30394
+ "panel",
30395
+ "card",
30396
+ "list",
30397
+ "grid",
30398
+ "form",
30399
+ "modal",
30400
+ "menu",
30401
+ "button",
30402
+ "icon",
30403
+ "avatar",
30404
+ "badge",
30405
+ "chip",
30406
+ "tooltip",
30407
+ "popover",
30408
+ "dropdown",
30409
+ "banner",
30410
+ "alert",
30411
+ "toast",
30412
+ "notification",
30413
+ "drawer",
30414
+ "sidebar",
30415
+ "navbar",
30416
+ "header",
30417
+ "footer",
30418
+ "hero",
30419
+ "cta",
30420
+ "cta-primary",
30421
+ "cta-secondary",
30422
+ "pricing",
30423
+ "price",
30424
+ "cost",
30425
+ "rate",
30426
+ "percent",
30427
+ "pct",
30428
+ "count",
30429
+ "total",
30430
+ "small",
30431
+ "medium",
30432
+ "large",
30433
+ "xl",
30434
+ "xxl",
30435
+ "tiny",
30436
+ "huge"
29948
30437
  ]);
29949
30438
  SOURCE_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
29950
30439
  SOURCE_ROOTS = ["src", "lib", "app", "components"];
@@ -29968,8 +30457,39 @@ var init_stale_function_reference = __esm({
29968
30457
  if (text.length < 3) continue;
29969
30458
  if (RESERVED.has(text.toLowerCase())) continue;
29970
30459
  if (context.exports.has(text)) continue;
29971
- const end = Math.min(source.length, span.index + text.length + 50);
29972
- if (!/\(/.test(source.slice(span.index, end))) continue;
30460
+ const lineEnd = source.indexOf("\n", span.index);
30461
+ const restOfLine = source.slice(
30462
+ span.index,
30463
+ lineEnd === -1 ? source.length : lineEnd
30464
+ );
30465
+ const closeTick = restOfLine.indexOf("`", 1);
30466
+ if (closeTick === -1) continue;
30467
+ const afterTick = restOfLine.slice(closeTick + 1);
30468
+ const directCall = /^\s*\(/.test(afterTick);
30469
+ let identifierRepeats = false;
30470
+ if (!directCall) {
30471
+ const afterSpan = restOfLine.slice(closeTick + 1);
30472
+ const needle = text + "(";
30473
+ identifierRepeats = afterSpan.indexOf(needle) !== -1;
30474
+ }
30475
+ if (!directCall && !identifierRepeats) continue;
30476
+ const beforeTickIdx = span.index - 1;
30477
+ const beforeChar = beforeTickIdx >= 0 ? source[beforeTickIdx] : "";
30478
+ if (beforeChar === "." || beforeChar === "|") continue;
30479
+ const parenStart = restOfLine.indexOf("(", closeTick);
30480
+ const parenEnd = restOfLine.indexOf(")", parenStart);
30481
+ if (parenStart !== -1 && parenEnd !== -1) {
30482
+ const inside = restOfLine.slice(parenStart + 1, parenEnd);
30483
+ const trimmed = inside.trim();
30484
+ if (looksLikeProseLabel(inside)) continue;
30485
+ const looksLikeTypeAnnotation = !inside.includes(":") && (/\b(string|number|boolean|null|undefined|object|array|required|optional|categorical|direct|n\/a|\bmapped\b|0[\-–][0-9]+|v[0-9]|higher is better|lower is better|added in|deprecated|pr-[0-9])\b/i.test(
30486
+ inside
30487
+ ) || // Short single-word label (≤ 24 chars, no `,`,
30488
+ // doesn't look like a function arg). Real function
30489
+ // calls are usually longer or contain commas.
30490
+ trimmed.length > 0 && trimmed.length <= 24 && !trimmed.includes(",") && /[a-zA-Z]/.test(trimmed));
30491
+ if (looksLikeTypeAnnotation) continue;
30492
+ }
29973
30493
  issues.push({
29974
30494
  ruleId: "docs/stale-function-reference",
29975
30495
  category: "docs",
@@ -30049,7 +30569,33 @@ var init_stale_package_reference = __esm({
30049
30569
  "jsx",
30050
30570
  "ok",
30051
30571
  "no",
30052
- "yes"
30572
+ "yes",
30573
+ // v0.18.6: common English adjectives / adverbs that frequently
30574
+ // appear in backticked prose but are not package names.
30575
+ "aspirational",
30576
+ "concrete",
30577
+ "abstract",
30578
+ "inline",
30579
+ "exposed",
30580
+ "deprecated",
30581
+ "experimental",
30582
+ "stable",
30583
+ "beta",
30584
+ "alpha",
30585
+ "wip",
30586
+ "draft",
30587
+ "final",
30588
+ "shim",
30589
+ "polyfill",
30590
+ "stub",
30591
+ "mock",
30592
+ "fake",
30593
+ "real",
30594
+ "false",
30595
+ "true",
30596
+ "optional",
30597
+ "required",
30598
+ "default"
30053
30599
  ]);
30054
30600
  stalePackageReferenceRule = createRule({
30055
30601
  id: "docs/stale-package-reference",
@@ -30271,7 +30817,15 @@ async function buildDocFreshness(cwd, config, options = {}) {
30271
30817
  continue;
30272
30818
  }
30273
30819
  const relPath = (0, import_node_path8.relative)(cwd, abs);
30274
- const context = { config, filePath: relPath, cwd };
30820
+ let packageName;
30821
+ try {
30822
+ const pkg = JSON.parse(
30823
+ (0, import_node_fs8.readFileSync)((0, import_node_path8.join)(cwd, "package.json"), "utf-8")
30824
+ );
30825
+ packageName = pkg.name;
30826
+ } catch {
30827
+ }
30828
+ const context = { config, filePath: relPath, cwd, packageName };
30275
30829
  const facts = { filePath: relPath, v2: { _source: source } };
30276
30830
  const ruleConfigs = [
30277
30831
  { rule: stalePackageReferenceRule, ruleId: "docs/stale-package-reference" },
@@ -30387,7 +30941,9 @@ var init_broken_link = __esm({
30387
30941
  if (target.startsWith("#")) continue;
30388
30942
  if (target.startsWith("//")) continue;
30389
30943
  if (target.startsWith("/")) continue;
30390
- const resolved = (0, import_node_path9.join)(docDir, target);
30944
+ const filePart = target.split("#")[0] ?? target;
30945
+ if (filePart === "") continue;
30946
+ const resolved = (0, import_node_path9.join)(docDir, filePart);
30391
30947
  if ((0, import_node_fs9.existsSync)(resolved)) continue;
30392
30948
  issues.push({
30393
30949
  ruleId: "docs/broken-link",