@webpro/remark-wrap-prose 1.0.0 → 1.0.1

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.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/index.js +31 -8
  3. package/package.json +4 -3
package/README.md CHANGED
@@ -8,6 +8,8 @@ level. Tables, code, and other non-prose blocks are left untouched. Wide CJK
8
8
  characters and emoji count as two columns. Words wider than the limit are never
9
9
  broken mid-word.
10
10
 
11
+ Inline code stays intact and retains its whitespace, even when a code span exceeds the limit.
12
+
11
13
  ## Install
12
14
 
13
15
  ```sh
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import fastStringTruncatedWidth from 'fast-string-truncated-width';
2
+ import { fromMarkdown } from 'mdast-util-from-markdown';
2
3
  import { editorConfigWidth } from './editorconfig.js';
3
4
 
4
5
  const DEFAULT_WIDTH = 80;
@@ -24,24 +25,42 @@ function displayWidth(value) {
24
25
  // ASCII soft-wrap whitespace (space, tab, newline, form feed, vertical tab).
25
26
  // Unicode spaces (no-break U+00A0, narrow no-break U+202F, …) are intentional
26
27
  // content and are left untouched, so they survive reflow.
27
- const SOFT_WHITESPACE = /[ \t\n\r\f\v]+/;
28
+ const SOFT_WHITESPACE = /[ \t\n\r\f\v]+/g;
29
+
30
+ function* proseWords(text, parseOptions) {
31
+ const codeSpans = [];
32
+ function visit(node) {
33
+ if (node.type === 'inlineCode') codeSpans.push(node.position);
34
+ else if (node.children) node.children.forEach(visit);
35
+ }
36
+ if (text.includes('`')) visit(fromMarkdown(text, parseOptions));
37
+
38
+ let span = 0;
39
+ let start = 0;
40
+ for (const match of text.matchAll(SOFT_WHITESPACE)) {
41
+ while (span < codeSpans.length && codeSpans[span].end.offset <= match.index) span++;
42
+ if (span < codeSpans.length && codeSpans[span].start.offset <= match.index) continue;
43
+ yield text.slice(start, match.index);
44
+ start = match.index + match[0].length;
45
+ }
46
+ yield text.slice(start);
47
+ }
28
48
 
29
49
  /**
30
- * Greedily wrap words to a maximum display width, collapsing only ASCII
31
- * soft-wrap whitespace. Words wider than the limit are kept intact (never
32
- * broken mid-word).
50
+ * Greedily wrap words to a maximum display width, collapsing only ASCII soft-wrap whitespace outside inline code. Words and code spans wider than the limit are kept intact.
33
51
  *
34
52
  * @param {string} text
35
53
  * @param {number} width
54
+ * @param {import('mdast-util-from-markdown').Options} parseOptions
36
55
  * @returns {string}
37
56
  */
38
- function fill(text, width) {
57
+ function fill(text, width, parseOptions) {
39
58
  /** @type {Array<string>} */
40
59
  const lines = [];
41
60
  let line = '';
42
61
  let lineWidth = 0;
43
62
 
44
- for (const word of text.split(SOFT_WHITESPACE)) {
63
+ for (const word of proseWords(text, parseOptions)) {
45
64
  if (!word) continue;
46
65
  const wordWidth = displayWidth(word);
47
66
  if (line === '') {
@@ -93,15 +112,19 @@ export default function remarkWrapProse(options = {}) {
93
112
  exit();
94
113
 
95
114
  const available = Math.max(1, width - (info.lineShift || 0));
115
+ const parseOptions = {
116
+ extensions: data.micromarkExtensions,
117
+ mdastExtensions: data.fromMarkdownExtensions
118
+ };
96
119
 
97
120
  const first = node.children[0];
98
121
  if (first?.type === 'gfmAlert') {
99
122
  const marker = value.slice(0, first.value.length);
100
- const body = fill(value.slice(first.value.length), available);
123
+ const body = fill(value.slice(first.value.length), available, parseOptions);
101
124
  return body ? marker + '\n' + body : marker;
102
125
  }
103
126
 
104
- return fill(value, available);
127
+ return fill(value, available, parseOptions);
105
128
  }
106
129
  }
107
130
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpro/remark-wrap-prose",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Remark plugin to wrap prose to a maximum line width",
5
5
  "keywords": [
6
6
  "unified",
@@ -38,10 +38,11 @@
38
38
  "access": "public"
39
39
  },
40
40
  "dependencies": {
41
- "fast-string-truncated-width": "^3.0.3"
41
+ "fast-string-truncated-width": "^3.0.3",
42
+ "mdast-util-from-markdown": "^2.1.0"
42
43
  },
43
44
  "devDependencies": {
44
- "@types/node": "^24.10.4",
45
+ "@types/node": "^26.6.6",
45
46
  "remark": "^15.0.1",
46
47
  "remark-directive": "^4.0.0"
47
48
  },