@herowcode/utils 1.1.5 → 1.1.6
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 +11 -0
- package/dist/string/index.d.ts +1 -0
- package/dist/string/index.d.ts.map +1 -1
- package/dist/string/index.esm.js +1 -0
- package/dist/string/index.js +1 -0
- package/dist/string/index.js.map +1 -1
- package/dist/string/markdown-to-text.d.ts +2 -0
- package/dist/string/markdown-to-text.d.ts.map +1 -0
- package/dist/string/markdown-to-text.esm.js +66 -0
- package/dist/string/markdown-to-text.js +66 -0
- package/dist/string/markdown-to-text.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,6 +66,17 @@ const embedUrl = generateYoutubeURL({
|
|
|
66
66
|
#### `shuffle<T>(array: T[]): T[]`
|
|
67
67
|
Returns a new array with the elements shuffled in random order.
|
|
68
68
|
|
|
69
|
+
#### `markdownToText(markdown: string): string`
|
|
70
|
+
|
|
71
|
+
Converts Markdown to plain text while preserving sensible line breaks. It strips formatting (bold, italic, strikethrough), removes headings, blockquotes, list markers, and table separators, keeps code fence inner content and inline code content, preserves image alt text and link text, decodes common HTML entities, and collapses excessive blank lines.
|
|
72
|
+
|
|
73
|
+
Example:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
markdownToText('# Hello\n**bold**\n\n`code`')
|
|
77
|
+
// "Hello\nbold\n\ncode"
|
|
78
|
+
```
|
|
79
|
+
|
|
69
80
|
```typescript
|
|
70
81
|
shuffle([1, 2, 3, 4]); // e.g., [3, 1, 4, 2]
|
|
71
82
|
```
|
package/dist/string/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./format-seconds-to-fragment";
|
|
|
5
5
|
export * from "./format-seconds-to-hms";
|
|
6
6
|
export * from "./format-string-to-time";
|
|
7
7
|
export * from "./kebab-case";
|
|
8
|
+
export * from "./markdown-to-text";
|
|
8
9
|
export * from "./remove-html-tags";
|
|
9
10
|
export * from "./slugify";
|
|
10
11
|
export * from "./snake-case";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/string/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA;AAClC,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/string/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA"}
|
package/dist/string/index.esm.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./format-seconds-to-fragment";
|
|
|
5
5
|
export * from "./format-seconds-to-hms";
|
|
6
6
|
export * from "./format-string-to-time";
|
|
7
7
|
export * from "./kebab-case";
|
|
8
|
+
export * from "./markdown-to-text";
|
|
8
9
|
export * from "./remove-html-tags";
|
|
9
10
|
export * from "./slugify";
|
|
10
11
|
export * from "./snake-case";
|
package/dist/string/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./format-seconds-to-fragment";
|
|
|
5
5
|
export * from "./format-seconds-to-hms";
|
|
6
6
|
export * from "./format-string-to-time";
|
|
7
7
|
export * from "./kebab-case";
|
|
8
|
+
export * from "./markdown-to-text";
|
|
8
9
|
export * from "./remove-html-tags";
|
|
9
10
|
export * from "./slugify";
|
|
10
11
|
export * from "./snake-case";
|
package/dist/string/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/string/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA4B;AAC5B,+CAA4B;AAC5B,0DAAuC;AACvC,+DAA4C;AAC5C,0DAAuC;AACvC,0DAAuC;AACvC,+CAA4B;AAC5B,qDAAkC;AAClC,4CAAyB;AACzB,+CAA4B;AAC5B,qDAAkC;AAClC,6CAA0B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/string/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA4B;AAC5B,+CAA4B;AAC5B,0DAAuC;AACvC,+DAA4C;AAC5C,0DAAuC;AACvC,0DAAuC;AACvC,+CAA4B;AAC5B,qDAAkC;AAClC,qDAAkC;AAClC,4CAAyB;AACzB,+CAA4B;AAC5B,qDAAkC;AAClC,6CAA0B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-to-text.d.ts","sourceRoot":"","sources":["../../src/string/markdown-to-text.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsFvD"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export function markdownToText(markdown) {
|
|
2
|
+
if (!markdown)
|
|
3
|
+
return "";
|
|
4
|
+
// normalize newlines
|
|
5
|
+
let text = markdown.replace(/\r\n?/g, "\n");
|
|
6
|
+
// Remove code fences but keep inner content (trim surrounding newlines to avoid extra blank lines)
|
|
7
|
+
text = text.replace(/```[\s\S]*?```/g, (m) => {
|
|
8
|
+
const inner = m.replace(/^```.*\n?/, "").replace(/```$/, "");
|
|
9
|
+
return inner.replace(/^\n+|\n+$/g, "");
|
|
10
|
+
});
|
|
11
|
+
// Remove inline code backticks
|
|
12
|
+
text = text.replace(/`([^`]+)`/g, "$1");
|
|
13
|
+
// Images: keep alt text if present
|
|
14
|
+
text = text.replace(/!\[([^\]]*)\]\((?:[^)]+)\)/g, "$1");
|
|
15
|
+
// Links: keep link text
|
|
16
|
+
text = text.replace(/\[([^\]]+)\]\((?:[^)]+)\)/g, "$1");
|
|
17
|
+
// Reference-style links: [text][id] -> text
|
|
18
|
+
text = text.replace(/\[([^\]]+)\]\s*\[[^\]]*\]/g, "$1");
|
|
19
|
+
// Remove footnote markers like [^1] (do this before we mutate surrounding lines)
|
|
20
|
+
text = text.replace(/\[\^[^\]]+\]/g, "");
|
|
21
|
+
// Remove reference definitions like: [id]: url (and footnote defs like [^1]: note)
|
|
22
|
+
// Remove the entire definition line including its trailing newline to avoid leaving blank lines
|
|
23
|
+
text = text.replace(/^\s*\[[^\]]+\]:\s*.*(?:\r\n?|\n)?/gm, "");
|
|
24
|
+
text = text.replace(/^\s*\[\^[^\]]+\]:\s*.*(?:\r\n?|\n)?/gm, "");
|
|
25
|
+
// Remove HTML tags but keep inner text
|
|
26
|
+
text = text.replace(/<\/?[^>]+>/g, "");
|
|
27
|
+
// Remove emphasis markers (bold/italic/strikethrough), preserve text
|
|
28
|
+
text = text.replace(/(\*\*|__)(.*?)\1/g, "$2");
|
|
29
|
+
text = text.replace(/(\*|_)(.*?)\1/g, "$2");
|
|
30
|
+
text = text.replace(/~~(.*?)~~/g, "$1");
|
|
31
|
+
// Remove headings (#, ##, etc.)
|
|
32
|
+
text = text.replace(/^\s{0,3}#{1,6}\s*/gm, "");
|
|
33
|
+
// Remove blockquote markers
|
|
34
|
+
text = text.replace(/^\s{0,3}>\s?/gm, "");
|
|
35
|
+
// Remove list markers (ordered and unordered)
|
|
36
|
+
text = text.replace(/^\s{0,3}([-+*]|\d+\.)\s+/gm, "");
|
|
37
|
+
// Remove table separator lines and keep table cell content by replacing pipes with spaced pipes
|
|
38
|
+
// Match the separator line and any trailing newline so we don't leave an empty line behind
|
|
39
|
+
// Remove separator lines entirely (don't insert an extra newline)
|
|
40
|
+
text = text.replace(/^\s*\|?(?:\s*:?-+:?\s*\|)+\s*(?:\r\n?|\n)?/gm, "");
|
|
41
|
+
text = text.replace(/\|/g, " | ");
|
|
42
|
+
// Trim leading whitespace on each line (fixes leading space introduced by replacing pipes)
|
|
43
|
+
text = text.replace(/^[ \t]+/gm, "");
|
|
44
|
+
// Fix table spacing edge-case: when a cell starts with two spaces before a digit (caused by adding spaces around pipes), collapse to a single space
|
|
45
|
+
text = text.replace(/\|\s{2}(?=\d)/g, "| ");
|
|
46
|
+
// Remove footnote markers like [^1]
|
|
47
|
+
text = text.replace(/\[\^[^\]]+\]/g, "");
|
|
48
|
+
// Remove any leftover footnote-definition fragments that may have been concatenated to the previous line
|
|
49
|
+
// e.g. "Text^1: note" -> "Text"
|
|
50
|
+
text = text.replace(/\^[0-9]+:\s*.*(?:\r\n?|\n)?/g, "");
|
|
51
|
+
// Decode a few common HTML entities
|
|
52
|
+
const entities = {
|
|
53
|
+
"&": "&",
|
|
54
|
+
"<": "<",
|
|
55
|
+
">": ">",
|
|
56
|
+
""": '"',
|
|
57
|
+
"'": "'",
|
|
58
|
+
};
|
|
59
|
+
text = text.replace(/&[a-zA-Z0-9#]+;/g, (e) => { var _a; return (_a = entities[e]) !== null && _a !== void 0 ? _a : e; });
|
|
60
|
+
// Trim trailing whitespace on each line
|
|
61
|
+
text = text.replace(/[ \t]+$/gm, "");
|
|
62
|
+
// Collapse excessive blank lines to at most two (preserve paragraph breaks)
|
|
63
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
64
|
+
// Final trim but preserve leading/trailing single newlines inside content as needed
|
|
65
|
+
return text.trim();
|
|
66
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export function markdownToText(markdown) {
|
|
2
|
+
if (!markdown)
|
|
3
|
+
return "";
|
|
4
|
+
// normalize newlines
|
|
5
|
+
let text = markdown.replace(/\r\n?/g, "\n");
|
|
6
|
+
// Remove code fences but keep inner content (trim surrounding newlines to avoid extra blank lines)
|
|
7
|
+
text = text.replace(/```[\s\S]*?```/g, (m) => {
|
|
8
|
+
const inner = m.replace(/^```.*\n?/, "").replace(/```$/, "");
|
|
9
|
+
return inner.replace(/^\n+|\n+$/g, "");
|
|
10
|
+
});
|
|
11
|
+
// Remove inline code backticks
|
|
12
|
+
text = text.replace(/`([^`]+)`/g, "$1");
|
|
13
|
+
// Images: keep alt text if present
|
|
14
|
+
text = text.replace(/!\[([^\]]*)\]\((?:[^)]+)\)/g, "$1");
|
|
15
|
+
// Links: keep link text
|
|
16
|
+
text = text.replace(/\[([^\]]+)\]\((?:[^)]+)\)/g, "$1");
|
|
17
|
+
// Reference-style links: [text][id] -> text
|
|
18
|
+
text = text.replace(/\[([^\]]+)\]\s*\[[^\]]*\]/g, "$1");
|
|
19
|
+
// Remove footnote markers like [^1] (do this before we mutate surrounding lines)
|
|
20
|
+
text = text.replace(/\[\^[^\]]+\]/g, "");
|
|
21
|
+
// Remove reference definitions like: [id]: url (and footnote defs like [^1]: note)
|
|
22
|
+
// Remove the entire definition line including its trailing newline to avoid leaving blank lines
|
|
23
|
+
text = text.replace(/^\s*\[[^\]]+\]:\s*.*(?:\r\n?|\n)?/gm, "");
|
|
24
|
+
text = text.replace(/^\s*\[\^[^\]]+\]:\s*.*(?:\r\n?|\n)?/gm, "");
|
|
25
|
+
// Remove HTML tags but keep inner text
|
|
26
|
+
text = text.replace(/<\/?[^>]+>/g, "");
|
|
27
|
+
// Remove emphasis markers (bold/italic/strikethrough), preserve text
|
|
28
|
+
text = text.replace(/(\*\*|__)(.*?)\1/g, "$2");
|
|
29
|
+
text = text.replace(/(\*|_)(.*?)\1/g, "$2");
|
|
30
|
+
text = text.replace(/~~(.*?)~~/g, "$1");
|
|
31
|
+
// Remove headings (#, ##, etc.)
|
|
32
|
+
text = text.replace(/^\s{0,3}#{1,6}\s*/gm, "");
|
|
33
|
+
// Remove blockquote markers
|
|
34
|
+
text = text.replace(/^\s{0,3}>\s?/gm, "");
|
|
35
|
+
// Remove list markers (ordered and unordered)
|
|
36
|
+
text = text.replace(/^\s{0,3}([-+*]|\d+\.)\s+/gm, "");
|
|
37
|
+
// Remove table separator lines and keep table cell content by replacing pipes with spaced pipes
|
|
38
|
+
// Match the separator line and any trailing newline so we don't leave an empty line behind
|
|
39
|
+
// Remove separator lines entirely (don't insert an extra newline)
|
|
40
|
+
text = text.replace(/^\s*\|?(?:\s*:?-+:?\s*\|)+\s*(?:\r\n?|\n)?/gm, "");
|
|
41
|
+
text = text.replace(/\|/g, " | ");
|
|
42
|
+
// Trim leading whitespace on each line (fixes leading space introduced by replacing pipes)
|
|
43
|
+
text = text.replace(/^[ \t]+/gm, "");
|
|
44
|
+
// Fix table spacing edge-case: when a cell starts with two spaces before a digit (caused by adding spaces around pipes), collapse to a single space
|
|
45
|
+
text = text.replace(/\|\s{2}(?=\d)/g, "| ");
|
|
46
|
+
// Remove footnote markers like [^1]
|
|
47
|
+
text = text.replace(/\[\^[^\]]+\]/g, "");
|
|
48
|
+
// Remove any leftover footnote-definition fragments that may have been concatenated to the previous line
|
|
49
|
+
// e.g. "Text^1: note" -> "Text"
|
|
50
|
+
text = text.replace(/\^[0-9]+:\s*.*(?:\r\n?|\n)?/g, "");
|
|
51
|
+
// Decode a few common HTML entities
|
|
52
|
+
const entities = {
|
|
53
|
+
"&": "&",
|
|
54
|
+
"<": "<",
|
|
55
|
+
">": ">",
|
|
56
|
+
""": '"',
|
|
57
|
+
"'": "'",
|
|
58
|
+
};
|
|
59
|
+
text = text.replace(/&[a-zA-Z0-9#]+;/g, (e) => { var _a; return (_a = entities[e]) !== null && _a !== void 0 ? _a : e; });
|
|
60
|
+
// Trim trailing whitespace on each line
|
|
61
|
+
text = text.replace(/[ \t]+$/gm, "");
|
|
62
|
+
// Collapse excessive blank lines to at most two (preserve paragraph breaks)
|
|
63
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
64
|
+
// Final trim but preserve leading/trailing single newlines inside content as needed
|
|
65
|
+
return text.trim();
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-to-text.js","sourceRoot":"","sources":["../../src/string/markdown-to-text.ts"],"names":[],"mappings":";;AAAA,wCAsFC;AAtFD,SAAgB,cAAc,CAAC,QAAgB;IAC7C,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAA;IAExB,qBAAqB;IACrB,IAAI,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAE3C,mGAAmG;IACnG,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAC5D,OAAO,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,+BAA+B;IAC/B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;IAEvC,mCAAmC;IACnC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAA;IAExD,wBAAwB;IACxB,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,IAAI,CAAC,CAAA;IAEvD,4CAA4C;IAC5C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,IAAI,CAAC,CAAA;IAEvD,iFAAiF;IACjF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAA;IAExC,mFAAmF;IACnF,gGAAgG;IAChG,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,qCAAqC,EAAE,EAAE,CAAC,CAAA;IAC9D,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,uCAAuC,EAAE,EAAE,CAAC,CAAA;IAEhE,uCAAuC;IACvC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;IAEtC,qEAAqE;IACrE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAA;IAC9C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;IAC3C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;IAEvC,gCAAgC;IAChC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAA;IAE9C,4BAA4B;IAC5B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAA;IAEzC,8CAA8C;IAC9C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAA;IAErD,gGAAgG;IAChG,2FAA2F;IAC3F,kEAAkE;IAClE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,8CAA8C,EAAE,EAAE,CAAC,CAAA;IACvE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAEjC,2FAA2F;IAC3F,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;IAEpC,oJAAoJ;IACpJ,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;IAE3C,oCAAoC;IACpC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAA;IAExC,yGAAyG;IACzG,gCAAgC;IAChC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAA;IAEvD,oCAAoC;IACpC,MAAM,QAAQ,GAA2B;QACvC,OAAO,EAAE,GAAG;QACZ,MAAM,EAAE,GAAG;QACX,MAAM,EAAE,GAAG;QACX,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE,GAAG;KACb,CAAA;IACD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,EAAE,EAAE,WAAC,OAAA,MAAA,QAAQ,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAA,EAAA,CAAC,CAAA;IAEhE,wCAAwC;IACxC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;IAEpC,4EAA4E;IAC5E,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IAEtC,oFAAoF;IACpF,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;AACpB,CAAC"}
|
package/package.json
CHANGED