@circlesac/mack 26.2.2 → 26.2.4

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.
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
14
  if (k2 === undefined) k2 = k;
4
15
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -79,7 +90,7 @@ function markdownToBlocks(body, options) {
79
90
  var lexer, tokenizer, origInlineText, tokens, blocks;
80
91
  return __generator(this, function (_a) {
81
92
  (0, validation_1.validateInput)(body);
82
- lexer = new marked_1.marked.Lexer();
93
+ lexer = new marked_1.marked.Lexer(__assign(__assign({}, marked_1.marked.defaults), { mangle: false }));
83
94
  tokenizer = lexer.tokenizer;
84
95
  origInlineText = tokenizer.inlineText;
85
96
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -26,11 +26,16 @@ var slack_1 = require("../slack");
26
26
  var validation_1 = require("../validation");
27
27
  var recursionDepth = 0;
28
28
  /**
29
- * Escapes &, <, > for Slack mrkdwn format.
29
+ * Escapes &, <, > for Slack mrkdwn format while preserving Slack special
30
+ * patterns: <@U…>, <#C…>, <!here>, <!channel>, <!everyone>, <https://…>.
30
31
  * Only used in the section/mrkdwn code path (not rich_text).
31
32
  */
33
+ var SLACK_MRKDWN_PATTERN = /(<(?:@[A-Z0-9]+(?:\|[^>]+)?|#[A-Z0-9]+(?:\|[^>]+)?|![a-z]+(?:\^[^>]+)*(?:\|[^>]+)?|https?:\/\/[^>]+)>)/g;
32
34
  function escapeForMrkdwn(text) {
33
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
35
+ return text
36
+ .split(SLACK_MRKDWN_PATTERN)
37
+ .map(function (part, i) { return (i % 2 === 1 ? part : part.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")); })
38
+ .join("");
34
39
  }
35
40
  function parsePlainText(element) {
36
41
  var _a;
@@ -59,8 +64,16 @@ function parseMrkdwn(element) {
59
64
  (0, validation_1.validateRecursionDepth)(recursionDepth);
60
65
  switch (element.type) {
61
66
  case "link": {
62
- var href = element.href && (0, validation_1.validateUrl)(element.href) ? element.href : "";
63
- if (!href) {
67
+ var href = element.href || "";
68
+ // Handle Slack pipe format: <url|text> parsed as autolink by marked
69
+ var pipeIndex = href.indexOf("|");
70
+ if (pipeIndex > 0) {
71
+ var url = href.slice(0, pipeIndex);
72
+ if ((0, validation_1.validateUrl)(url)) {
73
+ return "<".concat(url, "|").concat(href.slice(pipeIndex + 1), ">");
74
+ }
75
+ }
76
+ if (!(0, validation_1.validateUrl)(href)) {
64
77
  return element.tokens.flatMap(function (child) { return parseMrkdwn(child); }).join("");
65
78
  }
66
79
  return "<".concat(href, "|").concat(element.tokens.flatMap(function (child) { return parseMrkdwn(child); }).join(""), "> ");
package/package.json CHANGED
@@ -38,5 +38,5 @@
38
38
  "test": "vitest run"
39
39
  },
40
40
  "types": "build/src/index.d.ts",
41
- "version": "26.2.2"
41
+ "version": "26.2.4"
42
42
  }
package/src/index.ts CHANGED
@@ -50,7 +50,7 @@ export type { ListOptions, ParsingOptions } from "./types"
50
50
  export async function markdownToBlocks(body: string, options: ParsingOptions = {}): Promise<(KnownBlock | TableBlock | RichTextBlock | VideoBlock)[]> {
51
51
  validateInput(body)
52
52
 
53
- const lexer = new marked.Lexer()
53
+ const lexer = new marked.Lexer({ ...marked.defaults, mangle: false })
54
54
 
55
55
  // Override inlineText to prevent marked's default HTML entity escaping.
56
56
  // We want raw text so that:
@@ -39,11 +39,17 @@ type PhrasingToken =
39
39
  let recursionDepth = 0
40
40
 
41
41
  /**
42
- * Escapes &, <, > for Slack mrkdwn format.
42
+ * Escapes &, <, > for Slack mrkdwn format while preserving Slack special
43
+ * patterns: <@U…>, <#C…>, <!here>, <!channel>, <!everyone>, <https://…>.
43
44
  * Only used in the section/mrkdwn code path (not rich_text).
44
45
  */
46
+ const SLACK_MRKDWN_PATTERN = /(<(?:@[A-Z0-9]+(?:\|[^>]+)?|#[A-Z0-9]+(?:\|[^>]+)?|![a-z]+(?:\^[^>]+)*(?:\|[^>]+)?|https?:\/\/[^>]+)>)/g
47
+
45
48
  function escapeForMrkdwn(text: string): string {
46
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
49
+ return text
50
+ .split(SLACK_MRKDWN_PATTERN)
51
+ .map((part, i) => (i % 2 === 1 ? part : part.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")))
52
+ .join("")
47
53
  }
48
54
 
49
55
  function parsePlainText(element: PhrasingToken): string[] {
@@ -78,8 +84,16 @@ function parseMrkdwn(element: Exclude<PhrasingToken, marked.Tokens.Image>): stri
78
84
 
79
85
  switch (element.type) {
80
86
  case "link": {
81
- const href = element.href && validateUrl(element.href) ? element.href : ""
82
- if (!href) {
87
+ const href = element.href || ""
88
+ // Handle Slack pipe format: <url|text> parsed as autolink by marked
89
+ const pipeIndex = href.indexOf("|")
90
+ if (pipeIndex > 0) {
91
+ const url = href.slice(0, pipeIndex)
92
+ if (validateUrl(url)) {
93
+ return `<${url}|${href.slice(pipeIndex + 1)}>`
94
+ }
95
+ }
96
+ if (!validateUrl(href)) {
83
97
  return element.tokens.flatMap((child) => parseMrkdwn(child as Exclude<PhrasingToken, marked.Tokens.Image>)).join("")
84
98
  }
85
99
  return `<${href}|${element.tokens.flatMap((child) => parseMrkdwn(child as Exclude<PhrasingToken, marked.Tokens.Image>)).join("")}> `
@@ -489,8 +489,8 @@ i18n with plurals support and easy syntax.`
489
489
  const blocks = await markdownToBlocks("Hello <@U12345> how are you?")
490
490
  const allText = JSON.stringify(blocks)
491
491
  expect(allText).toContain('"type":"section"')
492
- // User mentions in section blocks use mrkdwn format
493
- expect(allText).toContain("&lt;@U12345&gt;")
492
+ // User mentions in section blocks are preserved as Slack mrkdwn syntax
493
+ expect(allText).toContain("<@U12345>")
494
494
  })
495
495
 
496
496
  it("should parse slack formatting in list items", async () => {