@jsenv/humanize 1.4.0 → 1.5.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.
@@ -1379,4 +1379,26 @@ const createCallOrderer = () => {
1379
1379
  return callWhenPreviousExecutionAreDone;
1380
1380
  };
1381
1381
 
1382
- export { ANSI, UNICODE, createCallOrderer, createDetailedMessage, distributePercentages, generateContentFrame, humanize, humanizeDuration, humanizeEllapsedTime, humanizeFileSize, humanizeMemory, humanizeMethodSymbol };
1382
+ const errorToMarkdown = error => {
1383
+ const errorIsAPrimitive = error === null || typeof error !== "object" && typeof error !== "function";
1384
+ if (errorIsAPrimitive) {
1385
+ return "```js\n".concat(error, "\n```");
1386
+ }
1387
+ return "```\n".concat(error.stack, "\n```");
1388
+ };
1389
+
1390
+ const errorToHTML = error => {
1391
+ const errorIsAPrimitive = error === null || typeof error !== "object" && typeof error !== "function";
1392
+ if (errorIsAPrimitive) {
1393
+ if (typeof error === "string") {
1394
+ return "<pre>".concat(escapeHtml(error), "</pre>");
1395
+ }
1396
+ return "<pre>".concat(JSON.stringify(error, null, " "), "</pre>");
1397
+ }
1398
+ return "<pre>".concat(escapeHtml(error.stack), "</pre>");
1399
+ };
1400
+ const escapeHtml = string => {
1401
+ return string.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1402
+ };
1403
+
1404
+ export { ANSI, UNICODE, createCallOrderer, createDetailedMessage, distributePercentages, errorToHTML, errorToMarkdown, generateContentFrame, humanize, humanizeDuration, humanizeEllapsedTime, humanizeFileSize, humanizeMemory, humanizeMethodSymbol };
@@ -1,5 +1,7 @@
1
- import { createSupportsColor, isUnicodeSupported, stripAnsi, emojiRegex, eastAsianWidth, clearTerminal, eraseLines } from "./jsenv_humanize_node_modules.js";
1
+ import { createSupportsColor, isUnicodeSupported, emojiRegex, eastAsianWidth } from "./jsenv_humanize_node_modules.js";
2
+ import stripAnsi from "strip-ansi";
2
3
  import { stripVTControlCharacters } from "node:util";
4
+ import ansiEscapes from "ansi-escapes";
3
5
  import "node:process";
4
6
  import "node:os";
5
7
  import "node:tty";
@@ -1407,6 +1409,44 @@ const createCallOrderer = () => {
1407
1409
  return callWhenPreviousExecutionAreDone;
1408
1410
  };
1409
1411
 
1412
+ const errorToMarkdown = (error) => {
1413
+ const errorIsAPrimitive =
1414
+ error === null ||
1415
+ (typeof error !== "object" && typeof error !== "function");
1416
+
1417
+ if (errorIsAPrimitive) {
1418
+ return `\`\`\`js
1419
+ ${error}
1420
+ \`\`\``;
1421
+ }
1422
+ return `\`\`\`
1423
+ ${error.stack}
1424
+ \`\`\``;
1425
+ };
1426
+
1427
+ const errorToHTML = (error) => {
1428
+ const errorIsAPrimitive =
1429
+ error === null ||
1430
+ (typeof error !== "object" && typeof error !== "function");
1431
+
1432
+ if (errorIsAPrimitive) {
1433
+ if (typeof error === "string") {
1434
+ return `<pre>${escapeHtml(error)}</pre>`;
1435
+ }
1436
+ return `<pre>${JSON.stringify(error, null, " ")}</pre>`;
1437
+ }
1438
+ return `<pre>${escapeHtml(error.stack)}</pre>`;
1439
+ };
1440
+
1441
+ const escapeHtml = (string) => {
1442
+ return string
1443
+ .replace(/&/g, "&amp;")
1444
+ .replace(/</g, "&lt;")
1445
+ .replace(/>/g, "&gt;")
1446
+ .replace(/"/g, "&quot;")
1447
+ .replace(/'/g, "&#039;");
1448
+ };
1449
+
1410
1450
  const renderBigSection = (params) => {
1411
1451
  return renderSection({
1412
1452
  width: 45,
@@ -1709,7 +1749,7 @@ const createDynamicLog = ({
1709
1749
  if (visualLineCount > rows) {
1710
1750
  if (clearTerminalAllowed) {
1711
1751
  clearAttemptResult = true;
1712
- return clearTerminal;
1752
+ return ansiEscapes.clearTerminal;
1713
1753
  }
1714
1754
  // the whole log cannot be cleared because it's vertically to long
1715
1755
  // (longer than terminal height)
@@ -1722,7 +1762,7 @@ const createDynamicLog = ({
1722
1762
  }
1723
1763
 
1724
1764
  clearAttemptResult = true;
1725
- return eraseLines(visualLineCount);
1765
+ return ansiEscapes.eraseLines(visualLineCount);
1726
1766
  };
1727
1767
 
1728
1768
  const update = (string) => {
@@ -1964,4 +2004,4 @@ const createTaskLog = (
1964
2004
  };
1965
2005
  };
1966
2006
 
1967
- export { ANSI, UNICODE, createCallOrderer, createDetailedMessage, createDynamicLog, createLogger, createTaskLog, distributePercentages, generateContentFrame, humanize, humanizeDuration, humanizeEllapsedTime, humanizeFileSize, humanizeMemory, humanizeMethodSymbol, renderBigSection, renderDetails, renderNamedSections, renderSection, startSpinner };
2007
+ export { ANSI, UNICODE, createCallOrderer, createDetailedMessage, createDynamicLog, createLogger, createTaskLog, distributePercentages, errorToHTML, errorToMarkdown, generateContentFrame, humanize, humanizeDuration, humanizeEllapsedTime, humanizeFileSize, humanizeMemory, humanizeMethodSymbol, renderBigSection, renderDetails, renderNamedSections, renderSection, startSpinner };
@@ -211,30 +211,6 @@ function isUnicodeSupported() {
211
211
  || env.TERMINAL_EMULATOR === 'JetBrains-JediTerm';
212
212
  }
213
213
 
214
- function ansiRegex({onlyFirst = false} = {}) {
215
- // Valid string terminator sequences are BEL, ESC\, and 0x9c
216
- const ST = '(?:\\u0007|\\u001B\\u005C|\\u009C)';
217
- const pattern = [
218
- `[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?${ST})`,
219
- '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))',
220
- ].join('|');
221
-
222
- return new RegExp(pattern, onlyFirst ? undefined : 'g');
223
- }
224
-
225
- const regex = ansiRegex();
226
-
227
- function stripAnsi(string) {
228
- if (typeof string !== 'string') {
229
- throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
230
- }
231
-
232
- // Even though the regex is global, we don't need to reset the `.lastIndex`
233
- // because unlike `.exec()` and `.test()`, `.replace()` does it automatically
234
- // and doing it manually has a performance penalty.
235
- return string.replace(regex, '');
236
- }
237
-
238
214
  const r = String.raw;
239
215
  const seq = r`(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})`;
240
216
  const sTags = r`\u{E0061}-\u{E007A}`;
@@ -625,85 +601,4 @@ function eastAsianWidth(codePoint, {ambiguousAsWide = false} = {}) {
625
601
  return 1;
626
602
  }
627
603
 
628
- /* globals WorkerGlobalScope, DedicatedWorkerGlobalScope, SharedWorkerGlobalScope, ServiceWorkerGlobalScope */
629
-
630
- const isBrowser = globalThis.window?.document !== undefined;
631
-
632
- globalThis.process?.versions?.node !== undefined;
633
-
634
- globalThis.process?.versions?.bun !== undefined;
635
-
636
- globalThis.Deno?.version?.deno !== undefined;
637
-
638
- globalThis.process?.versions?.electron !== undefined;
639
-
640
- globalThis.navigator?.userAgent?.includes('jsdom') === true;
641
-
642
- typeof WorkerGlobalScope !== 'undefined' && globalThis instanceof WorkerGlobalScope;
643
-
644
- typeof DedicatedWorkerGlobalScope !== 'undefined' && globalThis instanceof DedicatedWorkerGlobalScope;
645
-
646
- typeof SharedWorkerGlobalScope !== 'undefined' && globalThis instanceof SharedWorkerGlobalScope;
647
-
648
- typeof ServiceWorkerGlobalScope !== 'undefined' && globalThis instanceof ServiceWorkerGlobalScope;
649
-
650
- // Note: I'm intentionally not DRYing up the other variables to keep them "lazy".
651
- const platform = globalThis.navigator?.userAgentData?.platform;
652
-
653
- platform === 'macOS'
654
- || globalThis.navigator?.platform === 'MacIntel' // Even on Apple silicon Macs.
655
- || globalThis.navigator?.userAgent?.includes(' Mac ') === true
656
- || globalThis.process?.platform === 'darwin';
657
-
658
- platform === 'Windows'
659
- || globalThis.navigator?.platform === 'Win32'
660
- || globalThis.process?.platform === 'win32';
661
-
662
- platform === 'Linux'
663
- || globalThis.navigator?.platform?.startsWith('Linux') === true
664
- || globalThis.navigator?.userAgent?.includes(' Linux ') === true
665
- || globalThis.process?.platform === 'linux';
666
-
667
- platform === 'Android'
668
- || globalThis.navigator?.platform === 'Android'
669
- || globalThis.navigator?.userAgent?.includes(' Android ') === true
670
- || globalThis.process?.platform === 'android';
671
-
672
- const ESC = '\u001B[';
673
-
674
- !isBrowser && process.env.TERM_PROGRAM === 'Apple_Terminal';
675
- const isWindows = !isBrowser && process.platform === 'win32';
676
-
677
- isBrowser ? () => {
678
- throw new Error('`process.cwd()` only works in Node.js, not the browser.');
679
- } : process.cwd;
680
-
681
- const cursorUp = (count = 1) => ESC + count + 'A';
682
-
683
- const cursorLeft = ESC + 'G';
684
-
685
- const eraseLines = count => {
686
- let clear = '';
687
-
688
- for (let i = 0; i < count; i++) {
689
- clear += eraseLine + (i < count - 1 ? cursorUp() : '');
690
- }
691
-
692
- if (count) {
693
- clear += cursorLeft;
694
- }
695
-
696
- return clear;
697
- };
698
- const eraseLine = ESC + '2K';
699
- const eraseScreen = ESC + '2J';
700
-
701
- const clearTerminal = isWindows
702
- ? `${eraseScreen}${ESC}0f`
703
- // 1. Erases the screen (Only done in case `2` is not supported)
704
- // 2. Erases the whole screen including scrollback buffer
705
- // 3. Moves cursor to the top-left position
706
- // More info: https://www.real-world-systems.com/docs/ANSIcode.html
707
- : `${eraseScreen}${ESC}3J${ESC}H`;
708
-
709
- export { clearTerminal, createSupportsColor, eastAsianWidth, emojiRegex, eraseLines, isUnicodeSupported, stripAnsi };
604
+ export { createSupportsColor, eastAsianWidth, emojiRegex, isUnicodeSupported };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/humanize",
3
- "version": "1.4.0",
3
+ "version": "1.5.1",
4
4
  "description": "Generate messages meant to read by humans",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,7 +32,9 @@
32
32
  "/dist/",
33
33
  "/src/"
34
34
  ],
35
- "sideEffects": false,
35
+ "sideEffects": [
36
+ "./dist/node/jsenv_humanize_node_modules.js"
37
+ ],
36
38
  "scripts": {
37
39
  "build": "node ./scripts/build.mjs",
38
40
  "prepublishOnly": "npm run build"
@@ -0,0 +1,22 @@
1
+ export const errorToHTML = (error) => {
2
+ const errorIsAPrimitive =
3
+ error === null ||
4
+ (typeof error !== "object" && typeof error !== "function");
5
+
6
+ if (errorIsAPrimitive) {
7
+ if (typeof error === "string") {
8
+ return `<pre>${escapeHtml(error)}</pre>`;
9
+ }
10
+ return `<pre>${JSON.stringify(error, null, " ")}</pre>`;
11
+ }
12
+ return `<pre>${escapeHtml(error.stack)}</pre>`;
13
+ };
14
+
15
+ const escapeHtml = (string) => {
16
+ return string
17
+ .replace(/&/g, "&amp;")
18
+ .replace(/</g, "&lt;")
19
+ .replace(/>/g, "&gt;")
20
+ .replace(/"/g, "&quot;")
21
+ .replace(/'/g, "&#039;");
22
+ };
@@ -0,0 +1,14 @@
1
+ export const errorToMarkdown = (error) => {
2
+ const errorIsAPrimitive =
3
+ error === null ||
4
+ (typeof error !== "object" && typeof error !== "function");
5
+
6
+ if (errorIsAPrimitive) {
7
+ return `\`\`\`js
8
+ ${error}
9
+ \`\`\``;
10
+ }
11
+ return `\`\`\`
12
+ ${error.stack}
13
+ \`\`\``;
14
+ };
@@ -9,3 +9,5 @@ export { humanizeFileSize, humanizeMemory } from "./byte/byte.js";
9
9
  export { distributePercentages } from "./percentage/distribute_percentages.js";
10
10
  export { generateContentFrame } from "./content_frame/content_frame.js";
11
11
  export { createCallOrderer } from "./log/call_orderer.js";
12
+ export { errorToMarkdown } from "./error/error_to_markdown.js";
13
+ export { errorToHTML } from "./error/error_to_html.js";
package/src/main_node.js CHANGED
@@ -12,6 +12,8 @@ export { humanizeFileSize, humanizeMemory } from "./byte/byte.js";
12
12
  export { distributePercentages } from "./percentage/distribute_percentages.js";
13
13
  export { generateContentFrame } from "./content_frame/content_frame.js";
14
14
  export { createCallOrderer } from "./log/call_orderer.js";
15
+ export { errorToMarkdown } from "./error/error_to_markdown.js";
16
+ export { errorToHTML } from "./error/error_to_html.js";
15
17
 
16
18
  // node only
17
19
  export { renderSection, renderBigSection } from "./log/section.js";