Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-header

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-header - npm Package Compare versions

Comparing version 3.0.0 to 3.1.0

.eslintrc.yml

5

CHANGELOG.md

@@ -0,1 +1,6 @@

# 3.1.0
* Update to eslint 7.7.0
* Add a third option to specify number of linebreaks after the header. (#29)
# 3.0.0

@@ -2,0 +7,0 @@

283

lib/rules/header.js

@@ -8,3 +8,3 @@ "use strict";

function isPattern(object) {
return typeof object === "object" && object.hasOwnProperty("pattern");
return typeof object === "object" && Object.prototype.hasOwnProperty.call(object, "pattern");
}

@@ -26,13 +26,26 @@

// Returns either the first block comment or the first set of line comments that
// are ONLY separated by a single newline. Note that this does not actually
// check if they are at the start of the file since that is already checked by
// hasHeader().
function getLeadingComments(context, node) {
return node.body.length ?
context.getComments(node.body[0]).leading :
context.getComments(node).leading;
var all = excludeShebangs(context.getSourceCode().getAllComments(node.body.length ? node.body[0] : node));
if (all[0].type.toLowerCase() === "block") {
return [all[0]];
}
for (var i = 1; i < all.length; ++i) {
var txt = context.getSourceCode().getText().slice(all[i - 1].range[1], all[i].range[0]);
if (!txt.match(/^(\r\n|\r|\n)$/)) {
break;
}
}
return all.slice(0, i);
}
function genCommentBody(commentType, textArray, eol) {
function genCommentBody(commentType, textArray, eol, numNewlines) {
var eols = eol.repeat(numNewlines);
if (commentType === "block") {
return "/*" + textArray.join(eol) + "*/" + eol;
return "/*" + textArray.join(eol) + "*/" + eols;
} else {
return "//" + textArray.join(eol + "//") + eol;
return "//" + textArray.join(eol + "//") + eols;
}

@@ -50,7 +63,7 @@ }

function genPrependFixer(commentType, node, headerLines, eol) {
function genPrependFixer(commentType, node, headerLines, eol, numNewlines) {
return function(fixer) {
return fixer.insertTextBefore(
node,
genCommentBody(commentType, headerLines, eol)
genCommentBody(commentType, headerLines, eol, numNewlines)
);

@@ -60,7 +73,7 @@ };

function genReplaceFixer(commentType, context, leadingComments, headerLines, eol) {
function genReplaceFixer(commentType, context, leadingComments, headerLines, eol, numNewlines) {
return function(fixer) {
return fixer.replaceTextRange(
genCommentsRange(context, leadingComments, eol),
genCommentBody(commentType, headerLines, eol)
genCommentBody(commentType, headerLines, eol, numNewlines)
);

@@ -72,3 +85,4 @@ };

var lastOption = options.length > 0 ? options[options.length - 1] : null;
if (typeof lastOption === "object" && !Array.isArray(lastOption) && lastOption !== null && !lastOption.hasOwnProperty("pattern")) {
if (typeof lastOption === "object" && !Array.isArray(lastOption) && lastOption !== null
&& !Object.prototype.hasOwnProperty.call(lastOption, "pattern")) {
return lastOption;

@@ -90,112 +104,167 @@ }

module.exports = function(context) {
var options = context.options;
function hasHeader(src) {
if (src.substr(0, 2) === "#!") {
var m = src.match(/(\r\n|\r|\n)/);
if (m) {
src = src.slice(m.index + 1);
}
}
return src.substr(0, 2) === "/*" || src.substr(0, 2) === "//";
}
var eol = getEOL(options);
// If just one option then read comment from file
if (options.length === 1 || (options.length === 2 && findSettings(options))) {
var text = fs.readFileSync(context.options[0], "utf8");
options = commentParser(text);
function matchesLineEndings(src, num) {
for (var j = 0; j < num; ++j) {
var m = src.match(/^(\r\n|\r|\n)/);
if (m) {
src = src.slice(m.index + m[0].length);
} else {
return false;
}
}
return true;
}
var commentType = options[0];
var headerLines, fixLines = [];
// If any of the lines are regular expressions, then we can't
// automatically fix them. We set this to true below once we
// ensure none of the lines are of type RegExp
var canFix = false;
if (Array.isArray(options[1])) {
canFix = true;
headerLines = options[1].map(function(line) {
var isRegex = isPattern(line);
// Can only fix regex option if a template is also provided
if (isRegex && !line.template) {
canFix = false;
}
module.exports = {
meta: {
type: "layout",
fixable: "whitespace"
},
create: function(context) {
var options = context.options;
var numNewlines = options.length > 2 ? options[2] : 1;
var eol = getEOL(options);
// If just one option then read comment from file
if (options.length === 1 || (options.length === 2 && findSettings(options))) {
var text = fs.readFileSync(context.options[0], "utf8");
options = commentParser(text);
}
var commentType = options[0].toLowerCase();
var headerLines, fixLines = [];
// If any of the lines are regular expressions, then we can't
// automatically fix them. We set this to true below once we
// ensure none of the lines are of type RegExp
var canFix = false;
if (Array.isArray(options[1])) {
canFix = true;
headerLines = options[1].map(function(line) {
var isRegex = isPattern(line);
// Can only fix regex option if a template is also provided
if (isRegex && !line.template) {
canFix = false;
}
fixLines.push(line.template || line);
return isRegex ? new RegExp(line.pattern) : line;
});
} else if (isPattern(options[1])) {
var line = options[1];
headerLines = [new RegExp(line.pattern)];
fixLines.push(line.template || line);
return isRegex ? new RegExp(line.pattern) : line;
});
} else if (isPattern(options[1])) {
var line = options[1];
headerLines = [new RegExp(line.pattern)];
fixLines.push(line.template || line);
// Same as above for regex and template
canFix = !!line.template;
} else {
canFix = true;
headerLines = options[1].split(/\r?\n/);
fixLines = headerLines;
}
// Same as above for regex and template
canFix = !!line.template;
} else {
canFix = true;
headerLines = options[1].split(/\r?\n/);
fixLines = headerLines;
}
return {
Program: function(node) {
var leadingComments = excludeShebangs(getLeadingComments(context, node));
return {
Program: function(node) {
if (!hasHeader(context.getSourceCode().getText())) {
context.report({
loc: node.loc,
message: "missing header",
fix: genPrependFixer(commentType, node, fixLines, eol, numNewlines)
});
} else {
var leadingComments = getLeadingComments(context, node);
if (!leadingComments.length) {
context.report({
loc: node.loc,
message: "missing header",
fix: canFix ? genPrependFixer(commentType, node, fixLines, eol) : null
});
} else if (leadingComments[0].type.toLowerCase() !== commentType) {
context.report({
loc: node.loc,
message: "header should be a {{commentType}} comment",
data: {
commentType: commentType
},
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol) : null
});
} else {
if (commentType === "line") {
if (leadingComments.length < headerLines.length) {
if (!leadingComments.length) {
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol) : null
message: "missing header",
fix: canFix ? genPrependFixer(commentType, node, fixLines, eol, numNewlines) : null
});
return;
}
for (var i = 0; i < headerLines.length; i++) {
if (!match(leadingComments[i].value, headerLines[i])) {
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol) : null
});
return;
}
}
} else {
// if block comment pattern has more than 1 line, we also split the comment
var leadingLines = [leadingComments[0].value];
if (headerLines.length > 1) {
leadingLines = leadingComments[0].value.split(/\r?\n/);
}
} else if (leadingComments[0].type.toLowerCase() !== commentType) {
context.report({
loc: node.loc,
message: "header should be a {{commentType}} comment",
data: {
commentType: commentType
},
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol, numNewlines) : null
});
} else {
if (commentType === "line") {
if (leadingComments.length < headerLines.length) {
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol, numNewlines) : null
});
return;
}
for (var i = 0; i < headerLines.length; i++) {
if (!match(leadingComments[i].value, headerLines[i])) {
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol, numNewlines) : null
});
return;
}
}
var hasError = false;
if (leadingLines.length > headerLines.length) {
hasError = true;
}
for (i = 0; !hasError && i < headerLines.length; i++) {
if (!match(leadingLines[i], headerLines[i])) {
hasError = true;
}
}
var postLineHeader = context.getSourceCode().text.substr(leadingComments[headerLines.length - 1].range[1], numNewlines * 2);
if (!matchesLineEndings(postLineHeader, numNewlines)) {
context.report({
loc: node.loc,
message: "no newline after header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol, numNewlines) : null
});
}
if (hasError) {
if (canFix && headerLines.length > 1) {
fixLines = [fixLines.join(eol)];
} else {
// if block comment pattern has more than 1 line, we also split the comment
var leadingLines = [leadingComments[0].value];
if (headerLines.length > 1) {
leadingLines = leadingComments[0].value.split(/\r?\n/);
}
var hasError = false;
if (leadingLines.length > headerLines.length) {
hasError = true;
}
for (i = 0; !hasError && i < headerLines.length; i++) {
if (!match(leadingLines[i], headerLines[i])) {
hasError = true;
}
}
if (hasError) {
if (canFix && headerLines.length > 1) {
fixLines = [fixLines.join(eol)];
}
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol, numNewlines) : null
});
} else {
var postBlockHeader = context.getSourceCode().text.substr(leadingComments[0].range[1], numNewlines * 2);
if (!matchesLineEndings(postBlockHeader, numNewlines)) {
context.report({
loc: node.loc,
message: "no newline after header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol, numNewlines) : null
});
}
}
}
context.report({
loc: node.loc,
message: "incorrect header",
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol) : null
});
}
}
}
}
};
};
}
};
{
"name": "eslint-plugin-header",
"version": "3.0.0",
"version": "3.1.0",
"description": "ESLint plugin to ensure that files begin with given comment",

@@ -12,7 +12,7 @@ "main": "index.js",

"devDependencies": {
"eslint": "^5.12.0",
"mocha": "^5.2.0"
"eslint": "^7.7.0",
"mocha": "^8.1.1"
},
"peerDependencies": {
"eslint": ">=0.18.0"
"eslint": ">=7.7.0"
},

@@ -19,0 +19,0 @@ "keywords": [

@@ -10,3 +10,3 @@ eslint-plugin-header

This rule takes 1 or 2 arguments with an optional settings object.
This rule takes 1, 2 or 3 arguments with an optional settings object.

@@ -52,2 +52,57 @@ ### 1 argument

### 3 arguments
The optional third argument which defaults to 1 specifies the number of newlines that are enforced after the header.
Zero newlines:
```json
{
"plugins": [
"header"
],
"rules": {
"header/header": [2, "block", [" Copyright now","My Company "], 0]
}
}
```
```js
/* Copyright now
My Company */ console.log(1)
```
One newline (default)
```json
{
"plugins": [
"header"
],
"rules": {
"header/header": [2, "block", [" Copyright now","My Company "], 1]
}
}
```
```js
/* Copyright now
My Company */
console.log(1)
```
two newlines
```json
{
"plugins": [
"header"
],
"rules": {
"header/header": [2, "block", [" Copyright now","My Company "], 2]
}
}
```
```js
/* Copyright now
My Company */
console.log(1)
```
#### Regular expressions

@@ -54,0 +109,0 @@

@@ -19,3 +19,3 @@ "use strict";

code: "/*Copyright 2015, My Company*/",
options: ["block", "Copyright 2015, My Company"]
options: ["block", "Copyright 2015, My Company", 0]
},

@@ -57,11 +57,11 @@ {

code: "// Copyright 2017",
options: ["line", {pattern: "^ Copyright \\d+$"}]
options: ["line", {pattern: "^ Copyright \\d+$"}, 0]
},
{
code: "// Copyright 2017\n// Author: abc@example.com",
options: ["line", [{pattern: "^ Copyright \\d+$"}, {pattern: "^ Author: \\w+@\\w+\\.\\w+$"}]]
options: ["line", [{pattern: "^ Copyright \\d+$"}, {pattern: "^ Author: \\w+@\\w+\\.\\w+$"}], 0]
},
{
code: "/* Copyright 2017\n Author: abc@example.com */",
options: ["block", {pattern: "^ Copyright \\d{4}\\n Author: \\w+@\\w+\\.\\w+ $"}]
options: ["block", {pattern: "^ Copyright \\d{4}\\n Author: \\w+@\\w+\\.\\w+ $"}, 0]
},

@@ -74,3 +74,3 @@ {

" "
]]
], 0]
},

@@ -101,2 +101,22 @@ {

]]
},
{
code: "/*Copyright 2020, My Company*/\nconsole.log(1);",
options: ["block", "Copyright 2020, My Company", 1],
},
{
code: "/*Copyright 2020, My Company*/\n\nconsole.log(1);",
options: ["block", "Copyright 2020, My Company", 2],
},
{
code: "/*Copyright 2020, My Company*/\n\n// Log number one\nconsole.log(1);",
options: ["block", "Copyright 2020, My Company", 2],
},
{
code: "/*Copyright 2020, My Company*/\n\n/*Log number one*/\nconsole.log(1);",
options: ["block", "Copyright 2020, My Company", 2],
},
{
code: "/**\n * Copyright 2020\n * My Company\n **/\n\n/*Log number one*/\nconsole.log(1);",
options: ["block", "*\n * Copyright 2020\n * My Company\n *", 2],
}

@@ -219,4 +239,44 @@ ],

output: "/*************************\n * Copyright 2019\n * My Company\n *************************/\nconsole.log(1)"
},
{
code: "/*Copyright 2020, My Company*/console.log(1);",
options: ["block", "Copyright 2020, My Company", 2],
errors: [
{message: "no newline after header"}
],
output: "/*Copyright 2020, My Company*/\n\nconsole.log(1);"
},
{
code: "/*Copyright 2020, My Company*/console.log(1);",
options: ["block", "Copyright 2020, My Company", 1],
errors: [
{message: "no newline after header"}
],
output: "/*Copyright 2020, My Company*/\nconsole.log(1);"
},
{
code: "//Copyright 2020\n//My Company\nconsole.log(1);",
options: ["line", ["Copyright 2020", "My Company"], 2],
errors: [
{message: "no newline after header"}
],
output: "//Copyright 2020\n//My Company\n\nconsole.log(1);"
},
{
code: "/*Copyright 2020, My Company*/\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment",
options: ["block", "Copyright 2020, My Company", 2],
errors: [
{message: "no newline after header"}
],
output: "/*Copyright 2020, My Company*/\n\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment"
},
{
code: "//Copyright 2020\n//My Company\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment",
options: ["line", ["Copyright 2020", "My Company"], 2],
errors: [
{message: "no newline after header"}
],
output: "//Copyright 2020\n//My Company\n\nconsole.log(1);\n//Comment\nconsole.log(2);\n//Comment"
}
]
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc