formatferry 1.0.30 → 1.0.31

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 +55 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -58500,6 +58500,25 @@ function normalizeAtlassianHTML(html, domParser) {
58500
58500
 
58501
58501
  // ../../src/shared/confluence-slack-services.ts
58502
58502
  var import_turndown = __toESM(require_turndown_cjs(), 1);
58503
+ function escapeSlackEntities(text) {
58504
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
58505
+ }
58506
+ var ZERO_WIDTH_SPACE = "\u200B";
58507
+ function escapeSlackText(text) {
58508
+ return escapeSlackEntities(text).replace(
58509
+ /(^|[^\p{L}\p{N}])([*_~`])/gu,
58510
+ `$1${ZERO_WIDTH_SPACE}$2`
58511
+ );
58512
+ }
58513
+ function slackLabel(text) {
58514
+ return text.replace(/\|/g, "\uFF5C");
58515
+ }
58516
+ function escapeConfluenceText(text) {
58517
+ return text.replace(/([{}[\]\\])/g, "\\$1").replace(/(^|\n)([*#-])(?=\s)/g, "$1\\$2").replace(/(^|[^\p{L}\p{N}\\])([*_+\-^~])(?=\S)/gu, "$1\\$2").replace(
58518
+ /(?<=\S)([*_+\-^~])(?=$|[^\p{L}\p{N}])/gu,
58519
+ (m, c, offset, str) => str[offset - 1] === "\\" ? m : `\\${c}`
58520
+ );
58521
+ }
58503
58522
  function createSlackService(deps) {
58504
58523
  const service = new import_turndown.default({
58505
58524
  headingStyle: "atx",
@@ -58509,6 +58528,7 @@ function createSlackService(deps) {
58509
58528
  fence: "```",
58510
58529
  emDelimiter: "_"
58511
58530
  });
58531
+ service.escape = escapeSlackText;
58512
58532
  deps.addListRules(service);
58513
58533
  deps.addPdfPageMarkerRules(service);
58514
58534
  service.addRule("slackBold", {
@@ -58557,12 +58577,33 @@ function createSlackService(deps) {
58557
58577
  const fontFamily = style.toLowerCase();
58558
58578
  return fontFamily.includes("monospace") || fontFamily.includes("courier") || fontFamily.includes("consolas") || fontFamily.includes("monaco") || fontFamily.includes("menlo") || fontFamily.includes("source code") || fontFamily.includes("fira code") || fontFamily.includes("roboto mono") || fontFamily.includes("ubuntu mono");
58559
58579
  },
58560
- replacement: (content) => {
58561
- const trimmed = content.trim();
58580
+ replacement: (content, node) => {
58581
+ const trimmed = escapeSlackEntities((node.textContent || "").trim());
58562
58582
  if (!trimmed) return content;
58563
58583
  return trimmed.includes("`") ? `\`\` ${trimmed} \`\`` : `\`${trimmed}\``;
58564
58584
  }
58565
58585
  });
58586
+ service.addRule("slackCodeBlock", {
58587
+ filter: (node) => node.nodeName === "PRE",
58588
+ replacement: (_content, node) => {
58589
+ const code = (node.textContent || "").replace(/\n$/, "");
58590
+ return `
58591
+
58592
+ \`\`\`
58593
+ ${escapeSlackEntities(code)}
58594
+ \`\`\`
58595
+
58596
+ `;
58597
+ }
58598
+ });
58599
+ service.addRule("slackInlineCode", {
58600
+ filter: (node) => node.nodeName === "CODE" && node.parentNode?.nodeName !== "PRE",
58601
+ replacement: (content, node) => {
58602
+ const code = escapeSlackEntities(node.textContent || "");
58603
+ if (!code) return content;
58604
+ return code.includes("`") ? `\`\` ${code} \`\`` : `\`${code}\``;
58605
+ }
58606
+ });
58566
58607
  service.addRule("slackHeading", {
58567
58608
  filter: ["h1", "h2", "h3", "h4", "h5", "h6"],
58568
58609
  replacement: (content) => content.trim() ? `*${content.trim()}*
@@ -58599,8 +58640,8 @@ function createSlackService(deps) {
58599
58640
  service.addRule("slackLink", {
58600
58641
  filter: (node) => node.nodeName === "A" && !!node.getAttribute("href"),
58601
58642
  replacement: (content, node) => {
58602
- const href = node.getAttribute("href") || "";
58603
- const text = content.trim().replace(/\|/g, " ");
58643
+ const href = escapeSlackEntities(node.getAttribute("href") || "");
58644
+ const text = slackLabel(content.trim());
58604
58645
  if (!text || text === href) return `<${href}>`;
58605
58646
  return `<${href}|${text}>`;
58606
58647
  }
@@ -58608,15 +58649,15 @@ function createSlackService(deps) {
58608
58649
  service.addRule("slackImage", {
58609
58650
  filter: "img",
58610
58651
  replacement: (_content, node) => {
58611
- const src = node.getAttribute("src") || "";
58612
- const alt = (node.getAttribute("alt") || "image").replace(/\|/g, " ");
58652
+ const src = escapeSlackEntities(node.getAttribute("src") || "");
58653
+ const alt = slackLabel(escapeSlackEntities(node.getAttribute("alt") || "image"));
58613
58654
  return `<${src}|${alt}>`;
58614
58655
  }
58615
58656
  });
58616
58657
  service.addRule("slackTable", {
58617
58658
  filter: "table",
58618
58659
  replacement: (_content, node) => {
58619
- const plainText = deps.tableToPlainText(node);
58660
+ const plainText = escapeSlackEntities(deps.tableToPlainText(node));
58620
58661
  return `\`\`\`
58621
58662
  ${plainText}
58622
58663
  \`\`\`
@@ -58664,6 +58705,7 @@ function createConfluenceService(deps) {
58664
58705
  codeBlockStyle: "fenced",
58665
58706
  emDelimiter: "_"
58666
58707
  });
58708
+ service.escape = escapeConfluenceText;
58667
58709
  deps.addPdfPageMarkerRules(service);
58668
58710
  service.addRule("confluenceHeading", {
58669
58711
  filter: ["h1", "h2", "h3", "h4", "h5", "h6"],
@@ -58754,7 +58796,10 @@ ${codeContent}
58754
58796
  const fontFamily = style.toLowerCase();
58755
58797
  return fontFamily.includes("monospace") || fontFamily.includes("courier") || fontFamily.includes("consolas") || fontFamily.includes("monaco") || fontFamily.includes("menlo") || fontFamily.includes("source code") || fontFamily.includes("fira code") || fontFamily.includes("roboto mono") || fontFamily.includes("ubuntu mono");
58756
58798
  },
58757
- replacement: (content) => content.trim() ? `{{${content.trim().replace(/}+/g, (m) => m.split("").join(" "))}}}` : content
58799
+ replacement: (content, node) => {
58800
+ const code = (node.textContent || "").trim();
58801
+ return code ? `{{${code.replace(/}+/g, (m) => m.split("").join(" "))}}}` : content;
58802
+ }
58758
58803
  });
58759
58804
  service.addRule("confluenceLink", {
58760
58805
  filter: (node) => node.nodeName === "A" && !!node.getAttribute("href"),
@@ -64544,8 +64589,8 @@ import { readFileSync as readFileSync5 } from "fs";
64544
64589
  import { resolve, dirname as dirname3 } from "path";
64545
64590
  import { fileURLToPath } from "url";
64546
64591
  var getVersion = () => {
64547
- if ("1.0.30") {
64548
- return "1.0.30";
64592
+ if ("1.0.31") {
64593
+ return "1.0.31";
64549
64594
  }
64550
64595
  try {
64551
64596
  const __dirname2 = dirname3(fileURLToPath(import.meta.url));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "formatferry",
3
- "version": "1.0.30",
3
+ "version": "1.0.31",
4
4
  "description": "FormatFerry CLI — Convert HTML, DOCX, PDF, XLSX, CSV, JSON, XML, PPTX to Markdown",
5
5
  "keywords": [
6
6
  "markdown",