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

markdownlint

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

markdownlint - npm Package Compare versions

Comparing version 0.0.4 to 0.0.5

.eslintignore

6

example/standalone.js

@@ -6,3 +6,7 @@ "use strict";

var options = {
"files": [ "good.md", "bad.md" ]
"files": [ "good.md", "bad.md" ],
"strings": {
"good.string": "# good.string\n\nThis string passes all rules.",
"bad.string": "#bad.string\n\n#This string fails\tsome rules."
}
};

@@ -9,0 +13,0 @@

171

lib/markdownlint.js

@@ -56,82 +56,86 @@ "use strict";

// Lints a single file
function lintFile(file, config, synchronous, callback) {
// Callback for read file API
function readFile(err, contents) {
if (err) {
callback(err);
} else {
// Parse file into tokens and lines
var tokens = md.parse(contents, {});
var lines = contents.split(shared.newLineRe);
// Annotate tokens with line/lineNumber
tokens.forEach(function forToken(token) {
if (token.map) {
token.line = lines[token.map[0]];
token.lineNumber = token.map[0] + 1;
// Trim bottom of token to exclude whitespace lines
while (!(lines[token.map[1] - 1].trim())) {
token.map[1]--;
}
// Annotate children with lineNumber
var lineNumber = token.lineNumber;
(token.children || []).forEach(function forChild(child) {
child.lineNumber = lineNumber;
if ((child.type === "softbreak") || (child.type === "hardbreak")) {
lineNumber++;
}
});
// Lints a single string
function lintContent(content, config) {
// Parse content into tokens and lines
var tokens = md.parse(content, {});
var lines = content.split(shared.newLineRe);
// Annotate tokens with line/lineNumber
tokens.forEach(function forToken(token) {
if (token.map) {
token.line = lines[token.map[0]];
token.lineNumber = token.map[0] + 1;
// Trim bottom of token to exclude whitespace lines
while (!(lines[token.map[1] - 1].trim())) {
token.map[1]--;
}
// Annotate children with lineNumber
var lineNumber = token.lineNumber;
(token.children || []).forEach(function forChild(child) {
child.lineNumber = lineNumber;
if ((child.type === "softbreak") || (child.type === "hardbreak")) {
lineNumber++;
}
});
// Create parameters for rules
var params = {
"tokens": tokens,
"lines": lines
};
// Merge rules/tags and sanitize config
var mergedRules = {};
var ruleDefault = (config.default === undefined) || !!config.default;
rules.forEach(function forRule(rule) {
mergedRules[rule.name] = ruleDefault;
}
});
// Create parameters for rules
var params = {
"tokens": tokens,
"lines": lines
};
// Merge rules/tags and sanitize config
var mergedRules = {};
var ruleDefault = (config.default === undefined) || !!config.default;
rules.forEach(function forRule(rule) {
mergedRules[rule.name] = ruleDefault;
});
Object.keys(config).forEach(function forKey(key) {
var value = config[key];
if (value) {
if (!(value instanceof Object)) {
value = {};
}
} else {
value = false;
}
if (ruleToDescription[key]) {
mergedRules[key] = value;
} else if (tagToRules[key]) {
tagToRules[key].forEach(function forRule(rule) {
mergedRules[rule] = value;
});
Object.keys(config).forEach(function forKey(key) {
var value = config[key];
if (value) {
if (!(value instanceof Object)) {
value = {};
}
} else {
value = false;
}
if (ruleToDescription[key]) {
mergedRules[key] = value;
} else if (tagToRules[key]) {
tagToRules[key].forEach(function forRule(rule) {
mergedRules[rule] = value;
});
}
});
// Run each enabled rule
var result = {};
rules.forEach(function forRule(rule) {
if (mergedRules[rule.name]) {
// Configure rule
params.options = mergedRules[rule.name];
var errors = [];
rule.func(params, errors);
// Record any errors
if (errors.length) {
errors.sort(numberComparison);
result[rule.name] = errors.filter(uniqueFilterForSorted);
}
}
});
callback(null, result);
}
});
// Run each enabled rule
var result = {};
rules.forEach(function forRule(rule) {
if (mergedRules[rule.name]) {
// Configure rule
params.options = mergedRules[rule.name];
var errors = [];
rule.func(params, errors);
// Record any errors
if (errors.length) {
errors.sort(numberComparison);
result[rule.name] = errors.filter(uniqueFilterForSorted);
}
}
});
return result;
}
// Lints a single file
function lintFile(file, config, synchronous, callback) {
function lintContentWrapper(err, content) {
if (err) {
return callback(err);
}
var result = lintContent(content, config);
callback(null, result);
}
// Make a/synchronous call to read file
if (synchronous) {
readFile(null, fs.readFileSync(file, shared.utf8Encoding));
lintContentWrapper(null, fs.readFileSync(file, shared.utf8Encoding));
} else {
fs.readFile(file, shared.utf8Encoding, readFile);
fs.readFile(file, shared.utf8Encoding, lintContentWrapper);
}

@@ -160,7 +164,8 @@ }

var files = (options.files || []).slice();
var strings = options.strings || {};
var config = options.config || { "default": true };
var synchronous = (callback === markdownlintSynchronousCallback);
var results = new Results();
// Lint each input file
function lintFiles() {
// Helper to lint the next file in the array
function lintFilesArray() {
var file = files.shift();

@@ -170,8 +175,7 @@ if (file) {

if (err) {
callback(err);
} else {
// Record errors and lint next file
results[file] = result;
lintFiles();
return callback(err);
}
// Record errors and lint next file
results[file] = result;
lintFilesArray();
});

@@ -182,3 +186,10 @@ } else {

}
lintFiles();
// Lint strings
Object.keys(strings).forEach(function forKey(key) {
var result = lintContent(strings[key] || "", config);
results[key] = result;
});
// Lint files
lintFilesArray();
// Return results
if (synchronous) {

@@ -185,0 +196,0 @@ return results;

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

var current = null;
var lastWithMap = null;
var lastWithMap = { "map": [ 0, 1 ] };
tokens.forEach(function forToken(token) {

@@ -546,3 +546,3 @@ if ((token.type === "bullet_list_open") ||

list.items.forEach(function forItem(item) {
var re = new RegExp("^\\s*" + String(number) + "\\. ");
var re = new RegExp("^\\s*" + String(number) + "\\.");
if (!re.test(item.line)) {

@@ -576,3 +576,3 @@ errors.push(item.lineNumber);

var match = /^\s*\S+(\s+)/.exec(item.line);
if (match[1].length !== expectedSpaces) {
if (!match || (match[1].length !== expectedSpaces)) {
errors.push(item.lineNumber);

@@ -579,0 +579,0 @@ }

{
"name": "markdownlint",
"version": "0.0.4",
"version": "0.0.5",
"description": "A Node.js style checker and lint tool for Markdown files.",

@@ -18,13 +18,15 @@ "main": "lib/markdownlint.js",

"debug": "node debug node_modules/nodeunit/bin/nodeunit",
"lint": "eslint lib test & eslint --rule \"no-console: 0, no-shadow: 0\" example",
"example": "cd example & node standalone.js & grunt markdownlint & gulp markdownlint"
"lint": "eslint lib test & eslint --env browser --global markdownit --global markdownlint --rule \"no-unused-vars: 0, no-extend-native: 0, max-statements: 0\" demo & eslint --rule \"no-console: 0, no-shadow: 0\" example",
"build-demo": "copy node_modules\\markdown-it\\dist\\markdown-it.min.js demo & browserify lib/markdownlint.js --standalone markdownlint --exclude markdown-it --outfile demo/markdownlint-browser.js",
"example": "npm install through2 & cd example & node standalone.js & grunt markdownlint & gulp markdownlint"
},
"dependencies": {
"markdown-it": "^4.1.1"
"markdown-it": "^4.2.1"
},
"devDependencies": {
"eslint": "^0.19.0",
"istanbul": "^0.3.8",
"browserify": "^10.1.3",
"eslint": "^0.21.0",
"istanbul": "^0.3.13",
"nodeunit": "^0.9.1",
"q": "^1.2.0"
"q": "^1.4.0"
},

@@ -31,0 +33,0 @@ "keywords": [

@@ -36,2 +36,10 @@ # markdownlint

## Demonstration
[`markdownlint` demo](http://dlaa.me/markdownlint/), an interactive, in-browser
playground for learning and exploring.
> *Note*: `markdownlint` is not intended for use in the browser; the demo has
> polyfills and avoids referencing the `fs` module.
## Rules

@@ -147,2 +155,21 @@

#### options.strings
Type: `Object` mapping `String` to `String`
Map of identifiers to strings for linting.
When Markdown content is not available as files, it can be passed as strings.
The keys of the `strings` object are used to identify each input value in the
`result` summary.
Example:
```json
{
"readme": "# README\n...",
"changelog": "# CHANGELOG\n..."
}
```
#### options.config

@@ -210,3 +237,7 @@

var options = {
"files": [ "good.md", "bad.md" ]
"files": [ "good.md", "bad.md" ],
"strings": {
"good.string": "# good.string\n\nThis string passes all rules.",
"bad.string": "#bad.string\n\n#This string fails\tsome rules."
}
};

@@ -231,2 +262,5 @@

```text
bad.string: 3: MD010 Hard tabs
bad.string: 1: MD018 No space after hash on atx style header
bad.string: 3: MD018 No space after hash on atx style header
bad.md: 3: MD010 Hard tabs

@@ -251,2 +285,7 @@ bad.md: 1: MD018 No space after hash on atx style header

{
"good.string": {},
"bad.string": {
"MD010": [ 3 ],
"MD018": [ 1, 3 ]
},
"good.md": {},

@@ -339,2 +378,3 @@ "bad.md": {

* 0.0.4 - Add tests MD033-MD040, update dependencies.
* 0.0.5 - Add `strings` option to enable file-less scenarios, add in-browser demo.

@@ -341,0 +381,0 @@ [npm-image]: https://img.shields.io/npm/v/markdownlint.svg

@@ -10,2 +10,3 @@ "use strict";

var rules = require("../lib/rules");
var polyfills = require("../demo/browser-polyfills");

@@ -162,2 +163,25 @@ function createTestForFile(file) {

module.exports.stringInputLineEndings = function stringInputLineEndings(test) {
test.expect(2);
var options = {
"strings": {
"cr": "One\rTwo\r#Three",
"lf": "One\nTwo\n#Three",
"crlf": "One\r\nTwo\r\n#Three",
"mixed": "One\rTwo\n#Three"
}
};
markdownlint(options, function callback(err, actualResult) {
test.ifError(err);
var expectedResult = {
"cr": { "MD018": [ 3 ] },
"lf": { "MD018": [ 3 ] },
"crlf": { "MD018": [ 3 ] },
"mixed": { "MD018": [ 3 ] }
};
test.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.done();
});
};
module.exports.defaultTrue = function defaultTrue(test) {

@@ -447,3 +471,3 @@ test.expect(2);

module.exports.filesNotModified = function filesNotModified(test) {
module.exports.filesArrayNotModified = function filesArrayNotModified(test) {
test.expect(2);

@@ -466,3 +490,3 @@ var files = [

test.ifError(err);
test.ok(result, "Did not get result for missing options.");
test.deepEqual(result, {}, "Did not get empty result for missing options.");
test.done();

@@ -472,7 +496,7 @@ });

module.exports.missingFiles = function missingFiles(test) {
module.exports.missingFilesAndStrings = function missingFilesAndStrings(test) {
test.expect(2);
markdownlint({}, function callback(err, result) {
test.ifError(err);
test.ok(result, "Did not get result for missing files.");
test.ok(result, "Did not get result for missing files/strings.");
test.done();

@@ -502,3 +526,3 @@ });

module.exports.badFileSync = function badFileSync(test) {
test.expect(3);
test.expect(4);
test.throws(function badFileCall() {

@@ -509,2 +533,3 @@ markdownlint.sync({

}, function testError(err) {
test.ok(err, "Did not get an error for bad file.");
test.ok(err instanceof Error, "Error not instance of Error.");

@@ -517,2 +542,22 @@ test.equal(err.code, "ENOENT", "Error code for bad file not ENOENT.");

module.exports.missingStringValue = function missingStringValue(test) {
test.expect(2);
markdownlint({
"strings": {
"undefined": undefined,
"null": null,
"empty": ""
}
}, function callback(err, result) {
test.ifError(err);
var expectedResult = {
"undefined": {},
"null": {},
"empty": {}
};
test.deepEqual(result, expectedResult, "Did not get empty results.");
test.done();
});
};
module.exports.readme = function readme(test) {

@@ -614,1 +659,49 @@ test.expect(95);

};
module.exports.typeAllFiles = function typeAllFiles(test) {
// Simulates typing each test file to validate handling of partial input
var files = fs.readdirSync("./test");
files.forEach(function forFile(file) {
if (/\.md$/.test(file)) {
var content = fs.readFileSync(
path.join("./test", file), shared.utf8Encoding);
while (content) {
markdownlint.sync({
"strings": {
"content": content
}
});
content = content.slice(0, -1);
}
}
});
test.done();
};
module.exports.trimPolyfills = function trimPolyfills(test) {
var inputs = [
"text text",
" text text ",
" text text ",
// ECMAScript Whitespace
"\u0009 text text \u0009",
"\u000b text text \u000b",
"\u000c text text \u000c",
"\u0020 text text \u0020",
"\u00a0 text text \u00a0",
"\ufeff text text \ufeff",
// ECMAScript LineTerminator
"\u000a text text \u000a",
"\u000d text text \u000d",
"\u2028 text text \u2028",
"\u2029 text text \u2029"
];
test.expect(inputs.length * 2);
inputs.forEach(function forInput(input) {
test.equal(polyfills.trimLeftPolyfill.call(input), input.trimLeft(),
"trimLeft incorrect for '" + input + "'");
test.equal(polyfills.trimRightPolyfill.call(input), input.trimRight(),
"trimRight incorrect for '" + input + "'");
});
test.done();
};

Sorry, the diff of this file is not supported yet

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