@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 CHANGED
@@ -1,9 +1,7 @@
1
- # @putout/processor-markdown [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL]
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 simport = createSimport(__filename);
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 simport('remark-stringify');
28
- const preset = await simport('remark-preset-lint-consistent');
29
- const jsonProcessor = await simport('@putout/processor-json');
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.map(toPlace);
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 {messages, value} = await unified()
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
+
@@ -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 simport('remark-parse');
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.2.4",
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": "http://github.com/coderaiser/putout",
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": "^3.5.0",
42
+ "@putout/test": "^4.0.0",
42
43
  "c8": "^7.5.0",
43
- "eslint": "^7.0.0",
44
+ "eslint": "^8.0.1",
44
45
  "eslint-plugin-node": "^11.0.0",
45
- "eslint-plugin-putout": "^8.0.0",
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"