@tony.ganchev/eslint-plugin-header 3.2.5 → 3.3.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/README.md CHANGED
@@ -20,7 +20,9 @@ and banner comments in JavaScript and TypeScript files.
20
20
  2. [Providing To-year in Auto-fix](#providing-to-year-in-auto-fix)
21
21
  3. [Trailing Empty Lines Configuration](#trailing-empty-lines-configuration)
22
22
  4. [Line Endings](#line-endings)
23
- 3. [Examples](#examples)
23
+ 3. [Support for Leading Comments](#support-for-leading-comments)
24
+ 1. [Notes on Behavior](#notes-on-behavior)
25
+ 4. [Examples](#examples)
24
26
  4. [Comparison to Alternatives](#comparison-to-alternatives)
25
27
  1. [Compared to eslint-plugin-headers](#compared-to-eslint-plugin-headers)
26
28
  1. [Health Scans](#health-scans)
@@ -659,6 +661,293 @@ export default defineConfig([
659
661
  Possible values are `"unix"` for `\n` and `"windows"` for `\r\n` line endings.
660
662
  The default value is `"os"` which means assume the system-specific line endings.
661
663
 
664
+ ### Support for Leading Comments
665
+
666
+ _NOTE: This feature is still experimental and as such may break between minor
667
+ versions and revisions._
668
+
669
+ _NOTE: This feature will **only** be available with the modern object-based
670
+ configuration._
671
+
672
+ Some frameworks such as [Jest](https://jestjs.io/) change behavior based on
673
+ pragma comments such as:
674
+
675
+ ```js
676
+ /** @jest-environement node */
677
+ ```
678
+
679
+ The problem with these is that they are not part of the header comment and
680
+ should be allowed to appear before the header comment. The `leadingComments`
681
+ option allows you to specify a set of comments that are allowed to appear before
682
+ the header comment. It is configured as an array of comments-matching rules
683
+ similar to the `header` section. For example to match the following header with
684
+ a leading pragma:
685
+
686
+ ```js
687
+ /** @jest-environement node */
688
+ /* Copyright 2015, My Company */
689
+ ```
690
+
691
+ ... we can use the following configuration:
692
+
693
+ ```ts
694
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
695
+ import { defineConfig } from "eslint/config";
696
+
697
+ export default defineConfig([
698
+ {
699
+ files: ["**/*.js"],
700
+ plugins: {
701
+ "@tony.ganchev": header
702
+ },
703
+ rules: {
704
+ "@tony.ganchev/header": [
705
+ "error",
706
+ {
707
+ header: {
708
+ commentType: "block",
709
+ lines: [" Copyright 2015, My Company "]
710
+ },
711
+ leadingComments: {
712
+ comments: [
713
+ {
714
+ commentType: "block",
715
+ lines: ["* @jest-environement node "]
716
+ }
717
+ ]
718
+ }
719
+ } as HeaderOptions
720
+ ]
721
+ }
722
+ }
723
+ ]);
724
+ ```
725
+
726
+ Assuming you need to tolerate more pragmas, you can have a longer list of
727
+ comments e.g.
728
+
729
+ ```ts
730
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
731
+ import { defineConfig } from "eslint/config";
732
+
733
+ export default defineConfig([
734
+ {
735
+ files: ["**/*.js"],
736
+ plugins: {
737
+ "@tony.ganchev": header
738
+ },
739
+ rules: {
740
+ "@tony.ganchev/header": [
741
+ "error",
742
+ {
743
+ header: {
744
+ commentType: "block",
745
+ lines: [" Copyright 2015, My Company "]
746
+ },
747
+ leadingComments: {
748
+ comments: [
749
+ {
750
+ commentType: "block",
751
+ lines: ["* @jest-environement node "]
752
+ },
753
+ {
754
+ commentType: "line",
755
+ lines: [" @ts-ignore"]
756
+ }
757
+ ]
758
+ }
759
+ } as HeaderOptions
760
+ ]
761
+ }
762
+ }
763
+ ]);
764
+ ```
765
+
766
+ You can also use file-based configuration for any of these allowed comments.
767
+
768
+ #### Notes on Behavior
769
+
770
+ There are a number of things to consider when validating headers when allowing
771
+ some leading comments. It is important to understand the algorithm behind.
772
+ During validation, the rule breaks up all comments before the first actual code
773
+ token based either on the beginning and end of a block comments or based on the
774
+ separation of line comments by more than one line. These discrete comment blocks
775
+ are then validated against both the header-matching rule and all the leading
776
+ comment-matching rules.
777
+
778
+ For each comment, header is tested first and if it matches, validation completes
779
+ successfully. If not, the algorithm verifies that the comment satisfies at least
780
+ one comment matcher and if so, validation moves to the next comment.
781
+
782
+ If the comment matches neither the header, nor any of the leading comment
783
+ matchers, validation fails. To provide good troubleshooting information, errors
784
+ are reported for the header matcher, followed by all leading comment matchers.
785
+ While the information may seem overwhelming, this helps developers understand
786
+ all possible failures and let them pick the essential one.
787
+
788
+ Let's have the following configuration example:
789
+
790
+ ```ts
791
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
792
+ import { defineConfig } from "eslint/config";
793
+
794
+ export default defineConfig([
795
+ {
796
+ files: ["**/*.js"],
797
+ plugins: {
798
+ "@tony.ganchev": header
799
+ },
800
+ rules: {
801
+ "@tony.ganchev/header": [
802
+ "error",
803
+ {
804
+ header: {
805
+ commentType: "block",
806
+ lines: [" Copyright 2015, My Company "]
807
+ },
808
+ leadingComments: {
809
+ comments: [
810
+ {
811
+ commentType: "block",
812
+ lines: ["* @jest-environement node "]
813
+ },
814
+ {
815
+ commentType: "line",
816
+ lines: [" @ts-ignore"]
817
+ }
818
+ ]
819
+ }
820
+ } as HeaderOptions
821
+ ]
822
+ }
823
+ }
824
+ ]);
825
+ ```
826
+
827
+ Let's lint the following piece of code:
828
+
829
+ ```js
830
+ /** @jest-environement node */
831
+ /* Copyright 2010, My Company */
832
+
833
+ console.log(1);
834
+ ```
835
+
836
+ The following errors would be shown:
837
+
838
+ ```bash
839
+ 2:1 error leading comment validation failed: should be a line comment
840
+ @tony.ganchev/header
841
+ 2:3 error header line does not match expected after this position;
842
+ expected: 'Copyright 2015, My Company'
843
+ @tony.ganchev/header
844
+ 2:3 error leading comment validation failed: line does not match expected
845
+ after this position; expected: '* @jest-environement node '
846
+ @tony.ganchev/header
847
+ ```
848
+
849
+ Notice how all errors are reported on the second line. That is because the first
850
+ line passes validation against the first leading comment matcher, while the
851
+ second fails validation against all matchers.
852
+
853
+ Requiring an empty line between line leading comments is important as it keeps
854
+ the rule simple and fast but needs to be kept into account. Let's take the
855
+ following configuration for example:
856
+
857
+ ```ts
858
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
859
+ import { defineConfig } from "eslint/config";
860
+
861
+ export default defineConfig([
862
+ {
863
+ files: ["**/*.js"],
864
+ plugins: {
865
+ "@tony.ganchev": header
866
+ },
867
+ rules: {
868
+ "@tony.ganchev/header": [
869
+ "error",
870
+ {
871
+ header: {
872
+ commentType: "block",
873
+ lines: [" Copyright 2015, My Company "]
874
+ },
875
+ leadingComments: {
876
+ comments: [
877
+ {
878
+ commentType: "line",
879
+ lines: [" foo"]
880
+ },
881
+ {
882
+ commentType: "line",
883
+ lines: [" bar"]
884
+ }
885
+ ]
886
+ }
887
+ } as HeaderOptions
888
+ ]
889
+ }
890
+ }
891
+ ]);
892
+ ```
893
+
894
+ This configuration would successfully lint any of the following snippets:
895
+
896
+ ```js
897
+ // foo
898
+
899
+ // bar
900
+ /* Copyright 2015, My Company */
901
+ console.log();
902
+ ```
903
+
904
+ ```js
905
+ // bar
906
+
907
+ // foo
908
+
909
+ /* Copyright 2015, My Company */
910
+ console.log();
911
+ ```
912
+
913
+ ```js
914
+ // bar
915
+
916
+ // bar
917
+ /* Copyright 2015, My Company */
918
+ console.log();
919
+ ```
920
+
921
+ It will not pass the following snippets though:
922
+
923
+ ```js
924
+ // foo
925
+ // bar
926
+
927
+ /* Copyright 2015, My Company */
928
+ console.log();
929
+ ```
930
+
931
+ ```js
932
+ // bar
933
+ // foo
934
+ /* Copyright 2015, My Company */
935
+ console.log();
936
+ ```
937
+
938
+ ```js
939
+ // bar
940
+ // bar
941
+
942
+ /* Copyright 2015, My Company */
943
+ console.log();
944
+ ```
945
+
946
+ Finally, it is worth noting that the current version accepts an arbitrary number
947
+ of empty lines in between comments. The only expectation still in place is that
948
+ there is no empty line after a shebang comment. Any of these details may change
949
+ through configuration in the future.
950
+
662
951
  ### Examples
663
952
 
664
953
  The following examples are all valid.
@@ -937,4 +1226,4 @@ Backward-compatibility does not cover the following functional aspects:
937
1226
 
938
1227
  ## License
939
1228
 
940
- MIT
1229
+ MIT, see [license file](./LICENSE.md) for more details.
@@ -36,7 +36,7 @@ module.exports = {
36
36
  * @param {RuleContext} context ESLint execution context.
37
37
  * @returns {SourceCode} The source-code object.
38
38
  */
39
- contextSourceCode: function(context) {
39
+ contextSourceCode: function (context) {
40
40
  return context.sourceCode
41
41
  || /** @type {RuleContext & { getSourceCode: () => SourceCode }} */(context).getSourceCode();
42
42
  }