eslint-plugin-baseline-js 0.7.3 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.mjs +98 -103
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -26,7 +26,7 @@ This plugin delegates detection to eslint-plugin-es-x and ESLint core (plus a fe
26
26
  - yarn: `yarn add -D eslint-plugin-baseline-js`
27
27
 
28
28
  Recommended
29
- - ESLint >= 8.57 (Flat Config)
29
+ - ESLint >= 9.29.0 and < 11 (Flat Config)
30
30
 
31
31
  ## Quick Start (Flat Config)
32
32
 
package/dist/index.mjs CHANGED
@@ -64403,71 +64403,45 @@ function addTypedInstanceMemberDetector(context, d, report) {
64403
64403
  //#region src/rules/feature-usage/builder.ts
64404
64404
  function buildListeners(context, opt) {
64405
64405
  const listeners = {};
64406
- function report(node, featureId) {
64407
- const msg = opt.messages[featureId] ?? `Feature '${featureId}' exceeds configured Baseline.`;
64408
- context.report({
64409
- node,
64410
- message: msg
64411
- });
64412
- }
64413
64406
  const ctxLike = context;
64414
64407
  const services = ctxLike.parserServices || ctxLike.sourceCode?.parserServices || {};
64415
64408
  const checker = services.program?.getTypeChecker?.();
64416
64409
  const useTyped = !!opt.typed && !!checker && !!services.esTreeNodeToTSNodeMap;
64417
- for (const d of opt.descriptors) switch (d.kind) {
64418
- case "newIdent":
64419
- mergeRuleListeners(listeners, addNewIdentDetector(context, d, report));
64420
- break;
64421
- case "newMember":
64422
- mergeRuleListeners(listeners, addNewMemberDetector(context, d, report));
64423
- break;
64424
- case "callStatic":
64425
- mergeRuleListeners(listeners, addCallStaticDetector(context, d, report));
64426
- break;
64427
- case "callGlobal":
64428
- mergeRuleListeners(listeners, addCallGlobalDetector(context, d, report));
64429
- break;
64430
- case "member":
64431
- mergeRuleListeners(listeners, addMemberDetector(context, d, report));
64432
- break;
64433
- case "staticMember":
64434
- mergeRuleListeners(listeners, addStaticMemberDetector(context, d, report));
64435
- break;
64436
- case "instanceMember":
64437
- if (useTyped) mergeRuleListeners(listeners, addTypedInstanceMemberDetector(context, d, report));
64438
- break;
64439
- case "callMemberWithArgs":
64440
- mergeRuleListeners(listeners, addCallMemberWithArgsDetector(context, d, report));
64441
- break;
64442
- case "newWithOptions": mergeRuleListeners(listeners, addNewWithOptionsDetector(context, d, report));
64410
+ for (const d of opt.descriptors) {
64411
+ function report(node) {
64412
+ opt.report(node, d);
64413
+ }
64414
+ switch (d.kind) {
64415
+ case "newIdent":
64416
+ mergeRuleListeners(listeners, addNewIdentDetector(context, d, report));
64417
+ break;
64418
+ case "newMember":
64419
+ mergeRuleListeners(listeners, addNewMemberDetector(context, d, report));
64420
+ break;
64421
+ case "callStatic":
64422
+ mergeRuleListeners(listeners, addCallStaticDetector(context, d, report));
64423
+ break;
64424
+ case "callGlobal":
64425
+ mergeRuleListeners(listeners, addCallGlobalDetector(context, d, report));
64426
+ break;
64427
+ case "member":
64428
+ mergeRuleListeners(listeners, addMemberDetector(context, d, report));
64429
+ break;
64430
+ case "staticMember":
64431
+ mergeRuleListeners(listeners, addStaticMemberDetector(context, d, report));
64432
+ break;
64433
+ case "instanceMember":
64434
+ if (useTyped) mergeRuleListeners(listeners, addTypedInstanceMemberDetector(context, d, report));
64435
+ break;
64436
+ case "callMemberWithArgs":
64437
+ mergeRuleListeners(listeners, addCallMemberWithArgsDetector(context, d, report));
64438
+ break;
64439
+ case "newWithOptions": mergeRuleListeners(listeners, addNewWithOptionsDetector(context, d, report));
64440
+ }
64443
64441
  }
64444
64442
  return listeners;
64445
64443
  }
64446
64444
  //#endregion
64447
- //#region src/rules/feature-usage/index.ts
64448
- const rule$6 = {
64449
- meta: {
64450
- type: "problem",
64451
- docs: { description: "Detect usage of Web APIs and JS builtins beyond configured Baseline (data-driven)." },
64452
- schema: [{
64453
- type: "object",
64454
- properties: {
64455
- descriptors: { type: "array" },
64456
- messages: { type: "object" }
64457
- },
64458
- additionalProperties: false
64459
- }]
64460
- },
64461
- create(context) {
64462
- const opt = context.options?.[0] ?? {};
64463
- return buildListeners(context, {
64464
- descriptors: opt.descriptors ?? [],
64465
- messages: opt.messages ?? {},
64466
- typed: !!opt.typed
64467
- });
64468
- }
64469
- };
64470
- //#endregion
64471
64445
  //#region src/rules/no-atomics-pause/index.ts
64472
64446
  const rule$5 = {
64473
64447
  meta: {
@@ -64713,6 +64687,52 @@ function listResolverPlugins() {
64713
64687
  return Object.keys(registry).sort();
64714
64688
  }
64715
64689
  //#endregion
64690
+ //#region src/orchestrator/messages.ts
64691
+ function baselineMessage(featureId, baseline, subject) {
64692
+ const feature = getFeatureRecord(featureId);
64693
+ const label = subject ?? `'${feature?.name ?? featureId}'`;
64694
+ if (baseline === "widely") return `${label} is not Baseline Widely available (${featureId}).`;
64695
+ if (baseline === "newly") return `${label} is not Baseline Newly available (${featureId}).`;
64696
+ if (feature?.status?.baseline === false) return `${label} has Limited availability and exceeds ${baseline} (${featureId}).`;
64697
+ return `${label} became Baseline in ${baselineYearLabel(feature?.status) ?? "unknown"} and exceeds ${baseline} (${featureId}).`;
64698
+ }
64699
+ function delegateSubject(name) {
64700
+ const separator = name.lastIndexOf(".");
64701
+ if (separator === -1) return `'${name}'`;
64702
+ const owner = name.slice(0, separator).replace(/\.prototype$/, "");
64703
+ return memberSubject(name.slice(separator + 1), owner);
64704
+ }
64705
+ function descriptorSubject(descriptor) {
64706
+ switch (descriptor.kind) {
64707
+ case "newIdent":
64708
+ case "callGlobal": return `'${descriptor.name}'`;
64709
+ case "newMember":
64710
+ case "callStatic":
64711
+ case "member":
64712
+ case "staticMember": return memberSubject(descriptor.prop, descriptor.base);
64713
+ case "instanceMember": return memberSubject(descriptor.prop, descriptor.iface);
64714
+ case "callMemberWithArgs":
64715
+ case "newWithOptions": return callSubject(descriptor);
64716
+ }
64717
+ }
64718
+ function memberSubject(name, owner) {
64719
+ return `'${name}' on ${owner}`;
64720
+ }
64721
+ function callSubject(descriptor) {
64722
+ const args = [];
64723
+ const objectArg = descriptor.objectArg;
64724
+ if (descriptor.kind === "callMemberWithArgs" && descriptor.stringArg) args[descriptor.stringArg.index] = descriptor.stringArg.values.map((value) => JSON.stringify(value)).join(" | ");
64725
+ if (objectArg) {
64726
+ const properties = /* @__PURE__ */ new Map();
64727
+ for (const key of objectArg.hasKeys ?? []) properties.set(key, "...");
64728
+ for (const { key, values } of objectArg.keyValues ?? []) properties.set(key, values?.map((value) => JSON.stringify(value)).join(" | ") || "...");
64729
+ args[objectArg.index] = `{ ${Array.from(properties, ([key, value]) => `${key}: ${value}`).join(", ")} }`;
64730
+ }
64731
+ const argumentsText = Array.from(args, (argument) => argument ?? "...").join(", ");
64732
+ if (descriptor.kind === "newWithOptions") return `new ${descriptor.name}(${argumentsText})`;
64733
+ return `${descriptor.viaCall ? `${descriptor.viaCall.prop}().` : ""}${descriptor.prop}(${argumentsText})`;
64734
+ }
64735
+ //#endregion
64716
64736
  //#region src/orchestrator/use-baseline.ts
64717
64737
  function buildDelegateContext(ctx, overrides) {
64718
64738
  const src = ctx;
@@ -64732,15 +64752,6 @@ registerSelfRules({
64732
64752
  "no-math-sum-precise": rule$2,
64733
64753
  "no-temporal": rule$1
64734
64754
  });
64735
- function baselineMessage(featureId, baseline) {
64736
- const rec = getFeatureRecord(featureId);
64737
- const label = rec?.name || featureId;
64738
- const idSuffix = rec?.name ? ` (${featureId})` : "";
64739
- if (baseline === "widely") return `Feature '${label}'${idSuffix} is not a widely available Baseline feature.`;
64740
- if (baseline === "newly") return `Feature '${label}'${idSuffix} is not a newly available Baseline feature.`;
64741
- if (rec?.status?.baseline === false) return `Feature '${label}'${idSuffix} has Limited availability and exceeds ${baseline}.`;
64742
- return `Feature '${label}'${idSuffix} became Baseline in ${baselineYearLabel(rec?.status) ?? "unknown"} and exceeds ${baseline}.`;
64743
- }
64744
64755
  const rule = {
64745
64756
  meta: {
64746
64757
  type: "problem",
@@ -64896,14 +64907,16 @@ const rule = {
64896
64907
  },
64897
64908
  options: delegateOptions,
64898
64909
  report(arg) {
64899
- const node = typeof arg === "object" && arg !== null && "node" in arg ? arg.node : arg;
64900
- if (matchIgnoreNodeType) {
64901
- const t = node?.type;
64902
- if (t && matchIgnoreNodeType(t)) return;
64903
- }
64904
- ctx.report({
64905
- node,
64906
- message: baselineMessage(featureId, baseline)
64910
+ if ("node" in arg && matchIgnoreNodeType?.(arg.node.type)) return;
64911
+ const subject = arg.data?.name ? delegateSubject(String(arg.data.name)) : void 0;
64912
+ const message = baselineMessage(featureId, baseline, subject);
64913
+ if ("node" in arg) ctx.report({
64914
+ node: arg.node,
64915
+ message
64916
+ });
64917
+ else ctx.report({
64918
+ loc: arg.loc,
64919
+ message
64907
64920
  });
64908
64921
  }
64909
64922
  });
@@ -64934,35 +64947,17 @@ const rule = {
64934
64947
  const useTypesJs = resolveUseTypes(includeJsBuiltins);
64935
64948
  const typedEnabled = (useTypesWeb === "require" || useTypesJs === "require" || useTypesWeb === "auto" || useTypesJs === "auto") && typedAvailable;
64936
64949
  if (!typedEnabled) descriptors = descriptors.filter((d) => d.kind !== "instanceMember" && !d.typedOnly);
64937
- if (descriptors.length > 0) {
64938
- const messages = {};
64939
- for (const d of descriptors) messages[d.featureId] = baselineMessage(d.featureId, baseline);
64940
- const delegateCtx = buildDelegateContext(ctx, {
64941
- options: [typedEnabled ? {
64942
- descriptors,
64943
- messages,
64944
- typed: true
64945
- } : {
64946
- descriptors,
64947
- messages
64948
- }],
64949
- report(arg) {
64950
- const isObj = typeof arg === "object" && arg !== null;
64951
- const node = isObj && "node" in arg ? arg.node : arg;
64952
- if (matchIgnoreNodeType) {
64953
- const t = node?.type;
64954
- if (t && matchIgnoreNodeType(t)) return;
64955
- }
64956
- let msg;
64957
- if (isObj && typeof arg.message === "string") msg = arg.message;
64958
- ctx.report({
64959
- node,
64960
- message: msg
64961
- });
64962
- }
64963
- });
64964
- mergeRuleListeners(listeners, rule$6.create(delegateCtx));
64965
- }
64950
+ if (descriptors.length > 0) mergeRuleListeners(listeners, buildListeners(ctx, {
64951
+ descriptors,
64952
+ typed: typedEnabled,
64953
+ report(node, descriptor) {
64954
+ if (matchIgnoreNodeType?.(node.type)) return;
64955
+ ctx.report({
64956
+ node,
64957
+ message: baselineMessage(descriptor.featureId, baseline, descriptorSubject(descriptor))
64958
+ });
64959
+ }
64960
+ }));
64966
64961
  return listeners;
64967
64962
  }
64968
64963
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-baseline-js",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Enforce JavaScript Baseline (widely/newly/year) browser compatibility with a single ESLint rule. Prevent runtime errors by catching unsupported JavaScript features during development.",
5
5
  "license": "MIT",
6
6
  "type": "module",