oxlint-plugin-vize 0.391.0 → 0.404.9

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 +184 -5
  3. package/package.json +11 -11
package/README.md CHANGED
@@ -29,7 +29,7 @@ The bridge is optimized around Oxlint's per-rule execution model:
29
29
 
30
30
  ## Installation
31
31
 
32
- `oxlint-plugin-vize` targets Node 22 and Node 24+ (`^22 || >= 24`). In this repository, Vite+ reads `.node-version` for you, so the usual setup is:
32
+ `oxlint-plugin-vize` targets Node 22 and Node 24+ (`^22 || >= 24`). In this repository, Vite+ reads `package.json#devEngines.runtime` for you, so the usual setup is:
33
33
 
34
34
  ```bash
35
35
  vp install
package/dist/index.mjs CHANGED
@@ -95,7 +95,7 @@ if (import.meta.vitest) {
95
95
  }
96
96
  //#endregion
97
97
  //#region src/binding.ts
98
- function lintPatina(source, filename, settings, enabledRules) {
98
+ function lintPatina(source, filename, settings, enabledRules, ruleOptions) {
99
99
  return loadBinding().lintPatinaSfc(source, {
100
100
  filename,
101
101
  locale: settings.locale,
@@ -103,7 +103,8 @@ function lintPatina(source, filename, settings, enabledRules) {
103
103
  preset: settings.preset,
104
104
  enabledRules: enabledRules ? [...enabledRules] : void 0,
105
105
  typeAware: settings.typeAware,
106
- corsaPath: settings.corsaPath
106
+ corsaPath: settings.corsaPath,
107
+ ...ruleOptions
107
108
  });
108
109
  }
109
110
  function getPatinaRules() {
@@ -346,7 +347,8 @@ function getFileState(context) {
346
347
  evictLeastRecentlyUsedFileState();
347
348
  return state;
348
349
  }
349
- function getDiagnosticsForRule(context, state, ruleName) {
350
+ function getDiagnosticsForRule(context, state, ruleName, ruleOptions) {
351
+ if (ruleOptions != null) return getConfiguredRuleDiagnostics(context, state, ruleName, ruleOptions);
350
352
  if (state.allDiagnosticsByRule) {
351
353
  if (isTypeAwareRuleName(ruleName) && !state.allDiagnosticsIncludesTypeAware) {
352
354
  const settings = getVizeSettings(context);
@@ -389,6 +391,47 @@ function getDiagnosticsForRule(context, state, ruleName) {
389
391
  state.partialDiagnosticsByRule.clear();
390
392
  return diagnosticsForRule(state, state.allDiagnosticsByRule, ruleName);
391
393
  }
394
+ function getConfiguredRuleDiagnostics(context, state, ruleName, ruleOptions) {
395
+ const cacheKey = configuredRuleCacheKey(ruleName, ruleOptions);
396
+ const cached = state.partialDiagnosticsByRule.get(cacheKey);
397
+ if (cached) return cached;
398
+ const settings = getVizeSettings(context);
399
+ const ruleSettings = isTypeAwareRuleName(ruleName) ? {
400
+ ...settings,
401
+ typeAware: true
402
+ } : settings;
403
+ const diagnostics = lintPatina(state.source, state.filename, ruleSettings, [ruleName], ruleOptions).diagnostics;
404
+ const ruleDiagnostics = diagnosticsForRule(state, indexDiagnosticsByRule(diagnostics), ruleName);
405
+ state.partialDiagnosticsByRule.set(cacheKey, ruleDiagnostics);
406
+ return ruleDiagnostics;
407
+ }
408
+ function configuredRuleCacheKey(ruleName, ruleOptions) {
409
+ return [
410
+ ruleName,
411
+ ruleOptions.componentNameInTemplateCasing ?? "",
412
+ ruleOptions.customEventNameCasing ?? "",
413
+ ruleOptions.noMutatingProps == null ? "" : noMutatingPropsCacheKey(ruleOptions.noMutatingProps),
414
+ ruleOptions.sfcElementOrder == null ? "" : sfcElementOrderCacheKey(ruleOptions.sfcElementOrder),
415
+ ruleOptions.htmlSelfClosing == null ? "" : htmlSelfClosingCacheKey(ruleOptions.htmlSelfClosing),
416
+ ruleOptions.vOnEventHyphenation ?? "",
417
+ ruleOptions.attributeHyphenation ?? ""
418
+ ].join("\0");
419
+ }
420
+ function noMutatingPropsCacheKey(options) {
421
+ return options.shallowOnly === true ? "1" : "0";
422
+ }
423
+ function sfcElementOrderCacheKey(options) {
424
+ return (options.order ?? []).map((group) => Array.isArray(group) ? group.join("") : group).join("");
425
+ }
426
+ function htmlSelfClosingCacheKey(options) {
427
+ return [
428
+ options.html?.void ?? "",
429
+ options.html?.normal ?? "",
430
+ options.html?.component ?? "",
431
+ options.svg ?? "",
432
+ options.math ?? ""
433
+ ].join("/");
434
+ }
392
435
  function getScriptMap(state) {
393
436
  if (state.scriptMap !== void 0) return state.scriptMap;
394
437
  state.scriptMap = createSingleScriptMap(state.source, state.extractedScript, getSfcBlocks(state));
@@ -555,7 +598,8 @@ function createPatinaRule(ruleMeta) {
555
598
  return defineRule({
556
599
  meta: {
557
600
  type: ruleMeta.defaultSeverity === "error" ? "problem" : "suggestion",
558
- docs: { description: ruleMeta.description }
601
+ docs: { description: ruleMeta.description },
602
+ schema: ruleOptionsSchema(ruleMeta.name)
559
603
  },
560
604
  createOnce(context) {
561
605
  return { Program() {
@@ -566,7 +610,8 @@ function createPatinaRule(ruleMeta) {
566
610
  const helpLevel = settings.helpLevel ?? "full";
567
611
  const state = getFileState(context);
568
612
  const scriptMap = getScriptMap(state);
569
- const diagnostics = getDiagnosticsForRule(context, state, ruleMeta.name).filter((diagnostic) => shouldReportForCurrentProgram(diagnostic, state, scriptMap));
613
+ const ruleOptions = getRuleOptions(ruleMeta.name, contextOptions(context));
614
+ const diagnostics = getDiagnosticsForRule(context, state, ruleMeta.name, ruleOptions).filter((diagnostic) => shouldReportForCurrentProgram(diagnostic, state, scriptMap));
570
615
  if (diagnostics.length === 0) return;
571
616
  for (const diagnostic of diagnostics) {
572
617
  if (!markDiagnosticAsReported(state, diagnostic)) continue;
@@ -576,6 +621,140 @@ function createPatinaRule(ruleMeta) {
576
621
  }
577
622
  });
578
623
  }
624
+ function ruleOptionsSchema(ruleName) {
625
+ switch (ruleName) {
626
+ case "vue/component-name-in-template-casing": return [{ enum: ["PascalCase", "kebab-case"] }];
627
+ case "script/custom-event-name-casing": return [{ enum: ["camelCase", "kebab-case"] }];
628
+ case "vue/no-mutating-props": return [noMutatingPropsSchema()];
629
+ case "vue/sfc-element-order": return [sfcElementOrderSchema()];
630
+ case "vue/html-self-closing": return [htmlSelfClosingSchema()];
631
+ case "vue/v-on-event-hyphenation":
632
+ case "vue/attribute-hyphenation": return [{ enum: ["always", "never"] }];
633
+ default: return [];
634
+ }
635
+ }
636
+ function noMutatingPropsSchema() {
637
+ return {
638
+ type: "object",
639
+ properties: { shallowOnly: { type: "boolean" } },
640
+ additionalProperties: false
641
+ };
642
+ }
643
+ function sfcElementOrderSchema() {
644
+ const selector = { type: "string" };
645
+ return {
646
+ type: "object",
647
+ properties: { order: {
648
+ type: "array",
649
+ items: { oneOf: [selector, {
650
+ type: "array",
651
+ items: selector
652
+ }] }
653
+ } },
654
+ additionalProperties: false
655
+ };
656
+ }
657
+ function htmlSelfClosingSchema() {
658
+ const style = { enum: [
659
+ "always",
660
+ "never",
661
+ "any"
662
+ ] };
663
+ return {
664
+ type: "object",
665
+ properties: {
666
+ html: {
667
+ type: "object",
668
+ properties: {
669
+ void: style,
670
+ normal: style,
671
+ component: style
672
+ },
673
+ additionalProperties: false
674
+ },
675
+ svg: style,
676
+ math: style
677
+ },
678
+ additionalProperties: false
679
+ };
680
+ }
681
+ function contextOptions(context) {
682
+ const options = context.options;
683
+ return Array.isArray(options) ? options : [];
684
+ }
685
+ function getRuleOptions(ruleName, options) {
686
+ const firstOption = options[0];
687
+ switch (ruleName) {
688
+ case "vue/component-name-in-template-casing":
689
+ if (isComponentNameInTemplateCasingOption(firstOption)) return { componentNameInTemplateCasing: firstOption };
690
+ break;
691
+ case "script/custom-event-name-casing":
692
+ if (isCustomEventNameCasingOption(firstOption)) return { customEventNameCasing: firstOption };
693
+ break;
694
+ case "vue/no-mutating-props":
695
+ if (isNoMutatingPropsOption(firstOption)) return { noMutatingProps: firstOption };
696
+ break;
697
+ case "vue/sfc-element-order":
698
+ if (isSfcElementOrderOption(firstOption)) return { sfcElementOrder: firstOption };
699
+ break;
700
+ case "vue/html-self-closing":
701
+ if (isHtmlSelfClosingOption(firstOption)) return { htmlSelfClosing: firstOption };
702
+ break;
703
+ case "vue/v-on-event-hyphenation":
704
+ if (isHyphenationStyle(firstOption)) return { vOnEventHyphenation: firstOption };
705
+ break;
706
+ case "vue/attribute-hyphenation":
707
+ if (isHyphenationStyle(firstOption)) return { attributeHyphenation: firstOption };
708
+ break;
709
+ }
710
+ }
711
+ function isComponentNameInTemplateCasingOption(value) {
712
+ return value === "PascalCase" || value === "kebab-case";
713
+ }
714
+ function isCustomEventNameCasingOption(value) {
715
+ return value === "camelCase" || value === "kebab-case";
716
+ }
717
+ function isNoMutatingPropsOption(value) {
718
+ if (!isRecord$1(value)) return false;
719
+ return hasOnlyKeys(value, ["shallowOnly"]) && optionalBooleanField(value.shallowOnly);
720
+ }
721
+ function isSfcElementOrderOption(value) {
722
+ if (!isRecord$1(value)) return false;
723
+ return hasOnlyKeys(value, ["order"]) && (value.order === void 0 || Array.isArray(value.order) && value.order.every(isSfcElementOrderGroup));
724
+ }
725
+ function isSfcElementOrderGroup(value) {
726
+ return typeof value === "string" || Array.isArray(value) && value.every(isString);
727
+ }
728
+ function isHtmlSelfClosingOption(value) {
729
+ if (!isRecord$1(value)) return false;
730
+ return hasOnlyKeys(value, [
731
+ "html",
732
+ "svg",
733
+ "math"
734
+ ]) && optionField(value.svg) && optionField(value.math) && (value.html === void 0 || isRecord$1(value.html) && hasOnlyKeys(value.html, [
735
+ "void",
736
+ "normal",
737
+ "component"
738
+ ]) && optionField(value.html.void) && optionField(value.html.normal) && optionField(value.html.component));
739
+ }
740
+ function isHyphenationStyle(value) {
741
+ return value === "always" || value === "never";
742
+ }
743
+ function optionField(value) {
744
+ return value === void 0 || value === "always" || value === "never" || value === "any";
745
+ }
746
+ function optionalBooleanField(value) {
747
+ return value === void 0 || typeof value === "boolean";
748
+ }
749
+ function isString(value) {
750
+ return typeof value === "string";
751
+ }
752
+ function isRecord$1(value) {
753
+ return typeof value === "object" && value !== null && !Array.isArray(value);
754
+ }
755
+ function hasOnlyKeys(value, keys) {
756
+ return Object.keys(value).every((key) => keys.includes(key));
757
+ }
579
758
  var plugin_default = definePlugin({
580
759
  meta: { name: "vize" },
581
760
  rules: Object.fromEntries(getPatinaRules().map((ruleMeta) => [ruleMeta.name, createPatinaRule(ruleMeta)]))
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "devDependencies": {
13
13
  "@tsdown/css": "0.22.14",
14
14
  "@types/node": "25.9.2",
15
- "@vizejs/native": "0.391.0",
15
+ "@vizejs/native": "0.404.9",
16
16
  "tsdown": "0.22.14",
17
17
  "typescript": "6.0.3",
18
18
  "vite": "npm:@voidzero-dev/vite-plus-core@0.1.24",
@@ -43,14 +43,14 @@
43
43
  "main": "./dist/index.mjs",
44
44
  "name": "oxlint-plugin-vize",
45
45
  "optionalDependencies": {
46
- "@vizejs/native-darwin-arm64": "0.391.0",
47
- "@vizejs/native-darwin-x64": "0.391.0",
48
- "@vizejs/native-linux-arm64-gnu": "0.391.0",
49
- "@vizejs/native-linux-arm64-musl": "0.391.0",
50
- "@vizejs/native-linux-x64-gnu": "0.391.0",
51
- "@vizejs/native-linux-x64-musl": "0.391.0",
52
- "@vizejs/native-win32-arm64-msvc": "0.391.0",
53
- "@vizejs/native-win32-x64-msvc": "0.391.0"
46
+ "@vizejs/native-darwin-arm64": "0.404.9",
47
+ "@vizejs/native-darwin-x64": "0.404.9",
48
+ "@vizejs/native-linux-arm64-gnu": "0.404.9",
49
+ "@vizejs/native-linux-arm64-musl": "0.404.9",
50
+ "@vizejs/native-linux-x64-gnu": "0.404.9",
51
+ "@vizejs/native-linux-x64-musl": "0.404.9",
52
+ "@vizejs/native-win32-arm64-msvc": "0.404.9",
53
+ "@vizejs/native-win32-x64-msvc": "0.404.9"
54
54
  },
55
55
  "publishConfig": {
56
56
  "access": "public"
@@ -62,12 +62,12 @@
62
62
  },
63
63
  "type": "module",
64
64
  "types": "./dist/index.d.mts",
65
- "version": "0.391.0",
65
+ "version": "0.404.9",
66
66
  "scripts": {
67
67
  "build": "vp pack",
68
68
  "check": "vp check src vite.config.ts",
69
69
  "check:fix": "vp check --fix src vite.config.ts",
70
70
  "fmt": "vp fmt --write src vite.config.ts",
71
- "test": "vp pack && vp test run src/file-state.test.ts && node src/test.ts && node src/script-location.test.ts"
71
+ "test": "vp pack && vp test run src/file-state.test.ts && node src/test.ts && node src/script-location.test.ts && node src/casing-options.test.ts"
72
72
  }
73
73
  }