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

markdownlint-rule-search-replace

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

markdownlint-rule-search-replace - npm Package Compare versions

Comparing version 0.1.0 to 1.0.0

30

.markdownlint.json

@@ -102,16 +102,18 @@ {

"MD050": false,
"search-replace": [
{
"name": "ellipsis",
"message": "Do not use three dots '...' for ellipsis.",
"search": "...",
"replace": "…"
},
{
"name": "curly-double-quotes",
"message": "Do not use curly double quotes.",
"search_pattern": "/“|”/g",
"replace": "\""
}
],
"search-replace": {
"rules": [
{
"name": "ellipsis",
"message": "Do not use three dots '...' for ellipsis.",
"search": "...",
"replace": "…"
},
{
"name": "curly-double-quotes",
"message": "Do not use curly double quotes.",
"search_pattern": "/“|”/g",
"replace": "\""
}
]
}
}
{
"name": "markdownlint-rule-search-replace",
"version": "0.1.0",
"version": "1.0.0",
"description": "A custom markdownlint rule for search and replaces",

@@ -5,0 +5,0 @@ "main": "rule.js",

@@ -16,2 +16,3 @@ # markdownlint-rule-search-replace

Or specific cases like replace three backticks with one. [[ref](https://github.com/DavidAnson/markdownlint/issues/411)]
Or ban certain words.

@@ -32,3 +33,2 @@

### Using .markdownlint.json config file

@@ -39,16 +39,23 @@

```json
"search-replace": [
{
"name": "ellipsis",
"message": "Do not use three dots '...' for ellipsis.",
"search": "...",
"replace": "…"
},
{
"name": "curly-double-quotes",
"message": "Do not use curly double quotes.",
"search_pattern": "/“|”/g",
"replace": "\""
{
"default": true,
"MD001": false,
"search-replace": {
"rules": [
{
"name": "ellipsis",
"message": "Do not use three dots '...' for ellipsis.",
"search": "...",
"replace": "…",
"skip_code": true
},
{
"name": "curly-double-quotes",
"message": "Do not use curly double quotes.",
"search_pattern": "/“|”/g",
"replace": "\""
}
]
}
]
}
```

@@ -60,5 +67,6 @@ Here,

- `message`: corresponding message
- `search`: plain text to search
- `search`: text to search
- `search_pattern`: regex pattern to search. Include flags as well, as if you are defining a regex literal in JavaScript, e.g. `/http/g`.
- `replace`: The replacement text, e.g. `https`. Regex properties like `$1` can be used if `search_pattern` is being used.
- `replace`: The replacement string, e.g. `https`. Regex properties like `$1` can be used if `search_pattern` is being used.
- `skip_code`: Optional. All code(inline and block), which is inside backticks, will be skipped.

@@ -96,3 +104,3 @@ Note, `search` and `search_pattern` are interchangeable. The property `search` is used if both are supplied.

# or
markdonwlint test.md -r markdownlint-rule-search-replace --fix
markdownlint test.md -r markdownlint-rule-search-replace --fix
```

@@ -104,3 +112,3 @@

```
```js
const searchReplace = require("markdownlint-rule-search-replace");

@@ -107,0 +115,0 @@

@@ -5,2 +5,3 @@ // @ts-check

module.exports = {

@@ -13,38 +14,51 @@ names: ["search-replace"],

function: (params, onError) => {
if(!params.config.rules) {
return;
}
const content = params.lines.join("\n");
const [backticksData, htmlCommentData] = gatherInfo(content);
if (Array.isArray(params.config)) {
params.config.forEach((rule) => {
const regex = stringToRegex(rule.search || rule.search_pattern);
params.config.rules.forEach((rule) => {
const regex = stringToRegex(rule.search || rule.search_pattern);
let result;
while ((result = regex.exec(content)) !== null) {
const match = result[0];
const [lineNo, columnNo] = getLocation(params.lines, result.index);
let result;
while ((result = regex.exec(content)) !== null) {
const match = result[0];
let replacement = "";
if (rule.search) {
replacement = rule.replace;
} else {
replacement = match.replace(new RegExp(regex), rule.replace);
}
if(rule.skip_code && isCode(result.index, backticksData)) {
continue;
}
onError({
if(isHTMLComment(result.index, htmlCommentData)) {
continue;
}
const [lineNo, columnNo] = getLocation(params.lines, result.index);
let replacement = "";
if (rule.search) {
replacement = rule.replace;
} else {
replacement = match.replace(new RegExp(regex), rule.replace);
}
onError({
lineNumber: lineNo,
detail: rule.name + ": " + rule.message,
context: match,
range: [columnNo + 1, match.length],
fixInfo: {
lineNumber: lineNo,
detail: rule.name + ": " + rule.message,
context: match,
range: [columnNo + 1, match.length],
fixInfo: {
lineNumber: lineNo,
editColumn: columnNo + 1,
deleteCount: match.length,
insertText: replacement,
},
});
}
});
}
editColumn: columnNo + 1,
deleteCount: match.length,
insertText: replacement,
},
});
}
});
},
};
const escapeForRegExp = (str) => {

@@ -54,2 +68,8 @@ return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");

/**
* Converts string "/abc/ig" to new RegEx("abc", "ig").
* Or
* Converts string "abc" to new RegEx("abc", "g").
*/
const stringToRegex = (str) => {

@@ -66,2 +86,6 @@ let pattern = (str.match(/\/(.+)\/.*/) || [])[1];

/**
* Given position in the document returns line and column number.
*/
const getLocation = (lines, pos) => {

@@ -79,1 +103,64 @@ let lineNo = 1;

};
/**
* Collect start and end position data of all code fences and html comments.
*/
const gatherInfo = (content) => {
const backtickRgx = /`+/g;
const backticksData = [];
let match = null;
let lastLength = null;
while ((match = backtickRgx.exec(content)) !== null) {
const length = match[0].length;
const pos = match.index;
if(!lastLength) {
backticksData.push([length, pos]);
lastLength = length;
} else if(lastLength === length) {
backticksData.push([length, pos]);
lastLength = null;
}
}
const htmlCommentRgx = /<!--|-->/g;
const htmlCommentData = [];
while ((match = htmlCommentRgx.exec(content)) !== null) {
htmlCommentData.push([match[0].length, match.index]);
}
return [backticksData, htmlCommentData];
};
/**
* Tells if the position lies inside a code block.
*/
const isCode = (pos, data) => {
return isPartOf(pos, data);
};
/**
* Tells if the position lies inside an HTML comment.
*/
const isHTMLComment = (pos, data) => {
return isPartOf(pos, data);
};
/**
* Tells if the position lies inside any block in the 'data' array.
*/
const isPartOf = (pos, data) => {
for(let i = 0; i < data.length; i+=2 ) {
const start = data[i][1];
const end = data[i+1][0] + data[i+1][1];
if(start <= pos && pos <= end ) {
return true;
}
}
return false;
};

@@ -24,1 +24,3 @@ ---

Some _112_ text.
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