@putout/processor-markdown 5.2.4 → 5.6.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 +5 -3
- package/lib/markdown.js +14 -30
- package/lib/parse-place.js +37 -0
- package/lib/parse-store.js +1 -4
- package/lib/rules/index.mjs +36 -0
- package/lib/rules/merge-heading-spaces.mjs +52 -0
- package/lib/rules/remove-dependencies-status-badge.md +14 -0
- package/lib/rules/remove-dependencies-status-badge.mjs +53 -0
- package/lib/rules/remove-trailing-whitespaces-from-heading.mjs +32 -0
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
# @putout/processor-markdown [![NPM version][NPMIMGURL]][NPMURL]
|
|
1
|
+
# @putout/processor-markdown [![NPM version][NPMIMGURL]][NPMURL]
|
|
2
2
|
|
|
3
3
|
[NPMIMGURL]: https://img.shields.io/npm/v/@putout/processor-markdown.svg?style=flat&longCache=true
|
|
4
4
|
[NPMURL]: https://npmjs.org/package/@putout/processor-markdown "npm"
|
|
5
|
-
[DependencyStatusURL]: https://david-dm.org/coderaiser/putout?path=packages/processor-markdown
|
|
6
|
-
[DependencyStatusIMGURL]: https://david-dm.org/coderaiser/putout.svg?path=packages/processor-markdown
|
|
7
5
|
|
|
8
6
|
`putout` processor adds ability to get `js`, `json` and `ts` code from markdown files.
|
|
9
7
|
|
|
@@ -23,6 +21,10 @@ npm i @putout/processor-markdown -D
|
|
|
23
21
|
}
|
|
24
22
|
```
|
|
25
23
|
|
|
24
|
+
## Rules
|
|
25
|
+
|
|
26
|
+
- [Remove dependencies status badges](https://github.com/coderaiser/putout/tree/master/packages/processor-markdown/lib/rules/remove-dependencies-status-badge.md)
|
|
27
|
+
|
|
26
28
|
## License
|
|
27
29
|
|
|
28
30
|
MIT
|
package/lib/markdown.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {initParseStore} = require('./parse-store');
|
|
4
|
-
const {createSimport} = require('simport');
|
|
5
3
|
const once = require('once');
|
|
6
4
|
|
|
7
|
-
const
|
|
5
|
+
const {toPlace} = require('./parse-place');
|
|
6
|
+
const {initParseStore} = require('./parse-store');
|
|
8
7
|
|
|
9
8
|
const parseStore = initParseStore();
|
|
10
9
|
|
|
@@ -24,18 +23,11 @@ module.exports.files = [
|
|
|
24
23
|
];
|
|
25
24
|
|
|
26
25
|
const loadDependencies = once(async () => {
|
|
27
|
-
const stringify = await
|
|
28
|
-
const preset = await
|
|
29
|
-
const jsonProcessor = await
|
|
30
|
-
|
|
31
|
-
// Fix: TypeError: visit is not a function
|
|
32
|
-
//
|
|
33
|
-
// remark installs "uninst-util-visit" v2 using npm and has `module.exports = visit`
|
|
34
|
-
// but v3 has `export const visit = () => {}`
|
|
35
|
-
// and simport imports nearest version of "uninst-util-visit" which is v2
|
|
36
|
-
// that's why regular import should be used here while remark not transit to v3
|
|
26
|
+
const {default: stringify} = await import('remark-stringify');
|
|
27
|
+
const {default: preset} = await import('remark-preset-lint-consistent');
|
|
28
|
+
const {default: jsonProcessor} = await import('@putout/processor-json');
|
|
29
|
+
const {run} = await import('./rules/index.mjs');
|
|
37
30
|
const {visit} = await import('unist-util-visit');
|
|
38
|
-
// sometimes cannot load unified with simport on node v14
|
|
39
31
|
const {unified} = await import('unified');
|
|
40
32
|
|
|
41
33
|
return {
|
|
@@ -44,6 +36,7 @@ const loadDependencies = once(async () => {
|
|
|
44
36
|
visit,
|
|
45
37
|
preset,
|
|
46
38
|
jsonProcessor,
|
|
39
|
+
run,
|
|
47
40
|
};
|
|
48
41
|
});
|
|
49
42
|
|
|
@@ -52,6 +45,7 @@ module.exports.find = async (rawSource) => {
|
|
|
52
45
|
unified,
|
|
53
46
|
stringify,
|
|
54
47
|
preset,
|
|
48
|
+
run,
|
|
55
49
|
} = await loadDependencies();
|
|
56
50
|
|
|
57
51
|
await parseStore.init();
|
|
@@ -59,10 +53,12 @@ module.exports.find = async (rawSource) => {
|
|
|
59
53
|
const {messages} = await unified()
|
|
60
54
|
.use(parseStore)
|
|
61
55
|
.use(preset)
|
|
56
|
+
.use(run, {fix: false})
|
|
62
57
|
.use(stringify, stringifyOptions)
|
|
63
58
|
.process(rawSource);
|
|
64
59
|
|
|
65
|
-
return messages
|
|
60
|
+
return messages
|
|
61
|
+
.map(toPlace);
|
|
66
62
|
};
|
|
67
63
|
|
|
68
64
|
module.exports.fix = async (rawSource) => {
|
|
@@ -70,19 +66,18 @@ module.exports.fix = async (rawSource) => {
|
|
|
70
66
|
unified,
|
|
71
67
|
stringify,
|
|
72
68
|
preset,
|
|
69
|
+
run,
|
|
73
70
|
} = await loadDependencies();
|
|
74
71
|
|
|
75
72
|
await parseStore.init();
|
|
76
73
|
|
|
77
|
-
const {
|
|
74
|
+
const {value} = await unified()
|
|
78
75
|
.use(parseStore)
|
|
79
76
|
.use(preset)
|
|
77
|
+
.use(run, {fix: true})
|
|
80
78
|
.use(stringify, stringifyOptions)
|
|
81
79
|
.process(rawSource);
|
|
82
80
|
|
|
83
|
-
if (!messages.length)
|
|
84
|
-
return rawSource;
|
|
85
|
-
|
|
86
81
|
return value;
|
|
87
82
|
};
|
|
88
83
|
|
|
@@ -135,17 +130,6 @@ module.exports.merge = async (rawSource, list) => {
|
|
|
135
130
|
return value;
|
|
136
131
|
};
|
|
137
132
|
|
|
138
|
-
function toPlace({reason, line, column, source, ruleId}) {
|
|
139
|
-
return {
|
|
140
|
-
message: reason,
|
|
141
|
-
rule: `${ruleId} (${source})`,
|
|
142
|
-
position: {
|
|
143
|
-
line,
|
|
144
|
-
column,
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
133
|
const collect = ({list, visit}) => {
|
|
150
134
|
const jsonProcessor = require('@putout/processor-json');
|
|
151
135
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports.toPlace = function toPlace({reason, line, column, source, ruleId}) {
|
|
4
|
+
const {message, rule} = parseWatermark({
|
|
5
|
+
reason,
|
|
6
|
+
ruleId,
|
|
7
|
+
source,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
message,
|
|
12
|
+
rule,
|
|
13
|
+
position: {
|
|
14
|
+
line,
|
|
15
|
+
column,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function parseWatermark({reason, ruleId, source}) {
|
|
21
|
+
const [watermark, remarkRule, message] = reason.split(': ');
|
|
22
|
+
|
|
23
|
+
if (watermark === 'putout') {
|
|
24
|
+
const rule = `${remarkRule} (${source})`;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
rule,
|
|
28
|
+
message,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
message: reason,
|
|
34
|
+
rule: `${ruleId} (${source})`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
package/lib/parse-store.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {createSimport} = require('simport');
|
|
4
|
-
const simport = createSimport(__filename);
|
|
5
|
-
|
|
6
3
|
module.exports.initParseStore = () => {
|
|
7
4
|
let cache = null;
|
|
8
5
|
let parse = null;
|
|
@@ -24,7 +21,7 @@ module.exports.initParseStore = () => {
|
|
|
24
21
|
|
|
25
22
|
fn.init = async () => {
|
|
26
23
|
cache = null;
|
|
27
|
-
parse = await
|
|
24
|
+
({default: parse} = await import('remark-parse'));
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
fn.clear = async () => {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {lintRule} from 'unified-lint-rule';
|
|
2
|
+
import removeDependenciesStatusBadge from './remove-dependencies-status-badge.mjs';
|
|
3
|
+
import removeTrailingWhitespacesFromHeading from './remove-trailing-whitespaces-from-heading.mjs';
|
|
4
|
+
import mergeHeadingSpceces from './merge-heading-spaces.mjs';
|
|
5
|
+
|
|
6
|
+
const plugins = [
|
|
7
|
+
removeDependenciesStatusBadge,
|
|
8
|
+
removeTrailingWhitespacesFromHeading,
|
|
9
|
+
mergeHeadingSpceces,
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export const run = lintRule('remark-lint:run', (tree, file, options) => {
|
|
13
|
+
for (const {fix, traverse, report, name} of plugins) {
|
|
14
|
+
const nodes = [];
|
|
15
|
+
const push = nodes.push.bind(nodes);
|
|
16
|
+
|
|
17
|
+
traverse(tree, {
|
|
18
|
+
push,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
for (const node of nodes) {
|
|
22
|
+
if (options.fix) {
|
|
23
|
+
fix(node, tree);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const message = report(node);
|
|
28
|
+
file.message(`putout: ${name}: ${message}`, node);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const rules = {
|
|
34
|
+
plugins,
|
|
35
|
+
};
|
|
36
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const report = () => 'Merge heading spaces';
|
|
2
|
+
|
|
3
|
+
const fix = (heading) => {
|
|
4
|
+
const newChildren = [];
|
|
5
|
+
|
|
6
|
+
for (const [i, node] of heading.children.entries()) {
|
|
7
|
+
const nextNode = heading.children[i + 1];
|
|
8
|
+
|
|
9
|
+
if (bothSpaces(node, nextNode))
|
|
10
|
+
continue;
|
|
11
|
+
|
|
12
|
+
newChildren.push(node);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
heading.children = newChildren;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const traverse = (tree, {push}) => {
|
|
19
|
+
const [heading] = tree.children;
|
|
20
|
+
|
|
21
|
+
if (heading.type !== 'heading')
|
|
22
|
+
return;
|
|
23
|
+
|
|
24
|
+
for (const [i, node] of heading.children.entries()) {
|
|
25
|
+
const nextNode = heading.children[i + 1];
|
|
26
|
+
|
|
27
|
+
if (bothSpaces(node, nextNode)) {
|
|
28
|
+
push(heading);
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const bothSpaces = (node, nextNode) => {
|
|
35
|
+
if (!nextNode)
|
|
36
|
+
return false;
|
|
37
|
+
|
|
38
|
+
if (node.type !== 'text' || node.value !== ' ')
|
|
39
|
+
return false;
|
|
40
|
+
|
|
41
|
+
if (nextNode.type !== 'text' || nextNode.value !== ' ')
|
|
42
|
+
return false;
|
|
43
|
+
|
|
44
|
+
return true;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default {
|
|
48
|
+
name: 'merge-heading-spaces',
|
|
49
|
+
fix,
|
|
50
|
+
traverse,
|
|
51
|
+
report,
|
|
52
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Remove dependencies status badge (remove-dependencies-status-badge)
|
|
2
|
+
|
|
3
|
+
## Rule Details
|
|
4
|
+
|
|
5
|
+
```diff
|
|
6
|
+
# @putout/plugin-apply-replace-all [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL]
|
|
7
|
+
--# @putout/plugin-apply-replace-all [![NPM version][NPMIMGURL]][NPMURL]
|
|
8
|
+
|
|
9
|
+
[NPMIMGURL]: https://img.shields.io/npm/v/@putout/plugin-apply-replace-all.svg?style=flat&longCache=true
|
|
10
|
+
[NPMURL]: https://npmjs.org/package/@putout/plugin-apply-replace-all "npm"
|
|
11
|
+
-
|
|
12
|
+
-[DependencyStatusURL]: https://david-dm.org/coderaiser/putout?path=packages/plugin-apply-replace-all
|
|
13
|
+
-[DependencyStatusIMGURL]: https://david-dm.org/coderaiser/putout.svg?path=packages/plugin-apply-replace-all
|
|
14
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const report = () => 'Remove dependencies status badge';
|
|
2
|
+
|
|
3
|
+
const noop = () => {};
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
name: 'remove-dependencies-status-badge',
|
|
7
|
+
traverse,
|
|
8
|
+
fix,
|
|
9
|
+
report,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function fix(node, tree) {
|
|
13
|
+
const children = tree.children.filter(isDependencyStatus());
|
|
14
|
+
tree.children = children;
|
|
15
|
+
|
|
16
|
+
const [heading] = children;
|
|
17
|
+
|
|
18
|
+
if (heading.type !== 'heading')
|
|
19
|
+
return;
|
|
20
|
+
|
|
21
|
+
const headingChildren = heading.children.filter(isDependencyLink);
|
|
22
|
+
tree.children[0].children = headingChildren;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function traverse(tree, {push}) {
|
|
26
|
+
tree.children.filter(isDependencyStatus(push));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const isDependencyStatus = (push = noop) => (child) => {
|
|
30
|
+
if (child.type !== 'definition')
|
|
31
|
+
return true;
|
|
32
|
+
|
|
33
|
+
if (child.label === 'DependencyStatusURL') {
|
|
34
|
+
push(child);
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (child.label === 'DependencyStatusIMGURL')
|
|
39
|
+
return false;
|
|
40
|
+
|
|
41
|
+
return true;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const isDependencyLink = (child) => {
|
|
45
|
+
if (child.type !== 'linkReference')
|
|
46
|
+
return true;
|
|
47
|
+
|
|
48
|
+
if (child.children[0].label === 'DependencyStatusIMGURL')
|
|
49
|
+
return false;
|
|
50
|
+
|
|
51
|
+
return true;
|
|
52
|
+
};
|
|
53
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const report = () => 'Avoid trailing whitespaces';
|
|
2
|
+
|
|
3
|
+
const fix = (heading, tree) => {
|
|
4
|
+
const latest = heading.children[heading.children.length - 1];
|
|
5
|
+
|
|
6
|
+
if (latest.type === 'text' && latest.value === ' ')
|
|
7
|
+
heading.children = heading.children.slice(0, -1);
|
|
8
|
+
|
|
9
|
+
if (latest.type === 'text' && / $/.test(latest.value))
|
|
10
|
+
latest.value = latest.value.slice(0, -1);
|
|
11
|
+
|
|
12
|
+
tree.children[0].children = heading.children;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const traverse = (tree, {push}) => {
|
|
16
|
+
const [heading] = tree.children;
|
|
17
|
+
|
|
18
|
+
if (heading.type !== 'heading')
|
|
19
|
+
return;
|
|
20
|
+
|
|
21
|
+
const latest = heading.children[heading.children.length - 1];
|
|
22
|
+
|
|
23
|
+
if (latest.type === 'text' && / $/.test(latest.value))
|
|
24
|
+
push(heading);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
name: 'remove-trailing-whitespaces-from-heading',
|
|
29
|
+
fix,
|
|
30
|
+
traverse,
|
|
31
|
+
report,
|
|
32
|
+
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@putout/processor-markdown",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.6.0",
|
|
4
|
+
"type": "commonjs",
|
|
4
5
|
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
5
6
|
"description": "putout processor adds ability to parse markdown files and lint js snippets",
|
|
6
|
-
"homepage": "
|
|
7
|
+
"homepage": "https://github.com/coderaiser/putout/tree/master/packages/processor-markdown#readme",
|
|
7
8
|
"main": "lib/markdown.js",
|
|
8
9
|
"release": false,
|
|
9
10
|
"tag": false,
|
|
@@ -28,8 +29,8 @@
|
|
|
28
29
|
"remark-parse": "^10.0.0",
|
|
29
30
|
"remark-preset-lint-consistent": "^5.0.0",
|
|
30
31
|
"remark-stringify": "^10.0.0",
|
|
31
|
-
"simport": "^1.2.0",
|
|
32
32
|
"unified": "^10.0.0",
|
|
33
|
+
"unified-lint-rule": "^2.1.0",
|
|
33
34
|
"unist-util-visit": "^4.0.0"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
|
@@ -38,15 +39,16 @@
|
|
|
38
39
|
"markdown"
|
|
39
40
|
],
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"@putout/test": "^
|
|
42
|
+
"@putout/test": "^4.0.0",
|
|
42
43
|
"c8": "^7.5.0",
|
|
43
|
-
"eslint": "^
|
|
44
|
+
"eslint": "^8.0.1",
|
|
44
45
|
"eslint-plugin-node": "^11.0.0",
|
|
45
|
-
"eslint-plugin-putout": "^
|
|
46
|
+
"eslint-plugin-putout": "^13.0.0",
|
|
46
47
|
"lerna": "^4.0.0",
|
|
47
48
|
"madrun": "^8.0.1",
|
|
48
49
|
"nodemon": "^2.0.1",
|
|
49
|
-
"putout": "*"
|
|
50
|
+
"putout": "*",
|
|
51
|
+
"supertape": "^6.10.0"
|
|
50
52
|
},
|
|
51
53
|
"peerDependencies": {
|
|
52
54
|
"putout": ">=18"
|