slack-copy 1.1.1 → 1.2.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.
Files changed (2) hide show
  1. package/dist/index.js +24 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -23,6 +23,24 @@ const ITALIC = "\x01";
23
23
  const escapeEntities = (s) => s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
24
24
  const isTableSeparator = (line) => /^\s*\|?[\s:|-]*-[\s:|-]*\|[\s:|-]*$/.test(line ?? "");
25
25
  const isTableRow = (line) => /^\s*\|/.test(line);
26
+ // Cells of one pipe-table row; \| keeps the pipe it quotes. Unescaped: the
27
+ // mrkdwn and HTML flavours escape differently around alignTable.
28
+ const splitRow = (line) => line
29
+ .trim()
30
+ .replace(/^\|/, "")
31
+ .replace(/\|$/, "")
32
+ .replace(/\\\|/g, "\x02")
33
+ .split("|")
34
+ .map((cell) => cell.trim().replaceAll("\x02", "|"));
35
+ // Space-aligned monospace table: columns padded to the widest cell, a dashed
36
+ // separator under the header. Alignment only survives in monospace, so callers
37
+ // put the result in a code block.
38
+ function alignTable(rows) {
39
+ const widths = rows[0].map((_, c) => Math.max(...rows.map((row) => (row[c] ?? "").length)));
40
+ const lines = rows.map((row) => widths.map((w, c) => (row[c] ?? "").padEnd(w, " ")).join(" ").trimEnd());
41
+ const separator = widths.map((w) => "-".repeat(w)).join(" ");
42
+ return [lines[0], separator, ...lines.slice(1)].join("\n");
43
+ }
26
44
  // Inline formatting for one run of non-code text.
27
45
  function formatRun(text) {
28
46
  let out = escapeEntities(text);
@@ -69,16 +87,17 @@ export function toSlack(markdown) {
69
87
  out.push(escapeEntities(line));
70
88
  continue;
71
89
  }
72
- // Tables have no mrkdwn equivalent; a fence at least keeps them aligned.
90
+ // Tables have no mrkdwn equivalent; space-aligned cells in a fence at
91
+ // least keep the columns lined up.
73
92
  if (isTableRow(line) && isTableSeparator(lines[i + 1])) {
74
93
  const rows = [];
75
94
  while (i < lines.length && isTableRow(lines[i])) {
76
95
  if (!isTableSeparator(lines[i]))
77
- rows.push(escapeEntities(lines[i]));
96
+ rows.push(splitRow(lines[i]));
78
97
  i++;
79
98
  }
80
99
  i--;
81
- out.push("```", ...rows, "```");
100
+ out.push("```", alignTable(rows.map((row) => row.map(escapeEntities))), "```");
82
101
  continue;
83
102
  }
84
103
  const heading = line.match(/^#{1,6}\s+(.*?)\s*#*$/);
@@ -190,12 +209,12 @@ export function toHtml(markdown) {
190
209
  const rows = [];
191
210
  while (i < lines.length && isTableRow(lines[i])) {
192
211
  if (!isTableSeparator(lines[i]))
193
- rows.push(lines[i]);
212
+ rows.push(splitRow(lines[i]));
194
213
  i++;
195
214
  }
196
215
  i--;
197
216
  // Slack's composer has no table, but a code block keeps the columns lined up.
198
- out.push(`<pre><code>${escapeHtml(rows.join("\n"))}</code></pre>`);
217
+ out.push(`<pre><code>${escapeHtml(alignTable(rows))}</code></pre>`);
199
218
  continue;
200
219
  }
201
220
  const heading = line.match(/^#{1,6}\s+(.*?)\s*#*$/);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slack-copy",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Convert Markdown to Slack mrkdwn and put it on the clipboard",
5
5
  "type": "module",
6
6
  "author": {