fix-md-tables 1.1.1 → 1.1.3

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 (3) hide show
  1. package/README.md +3 -3
  2. package/lib/index.mjs +43 -12
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -27,7 +27,7 @@ Renders misaligned:
27
27
  Add ideographic spaces (U+3000) to cells with fewer emoji. Ideographic spaces also display as 2 columns, compensating for the width difference:
28
28
 
29
29
  ```markdown
30
- | Status  | Description  | Comments  |
30
+ | Status  | Description  | Comments |
31
31
  | -------- | -------------- | ---------- |
32
32
  | ✅ | ✅ Complete | ❌ |
33
33
  | 🚧 | 🚧 In Progress | ⚠️ |
@@ -134,9 +134,9 @@ Main function to fix table alignment in markdown content.
134
134
 
135
135
  Count emoji characters in a string.
136
136
 
137
- ### `stripIdeographicSpaces(str: string): string`
137
+ ### `normalizeIdeographicSpaces(str: string): string`
138
138
 
139
- Remove all ideographic spaces from a string.
139
+ Replace all ideographic spaces with 2 regular spaces (same visual width).
140
140
 
141
141
  ### `processTable(tableRows: string[]): string[]`
142
142
 
package/lib/index.mjs CHANGED
@@ -28,9 +28,9 @@ export function countEmoji(str) {
28
28
  return (str.match(EMOJI_REGEX) || []).length;
29
29
  }
30
30
 
31
- /** Remove all ideographic spaces from a string */
32
- export function stripIdeographicSpaces(str) {
33
- return str.replaceAll("\u3000", "");
31
+ /** Replace all ideographic spaces with 2 regular spaces (same visual width) */
32
+ export function normalizeIdeographicSpaces(str) {
33
+ return str.replaceAll("\u3000", " ");
34
34
  }
35
35
 
36
36
  /** Check if a line is a markdown table separator */
@@ -78,8 +78,11 @@ export function compensateSeparatorCell(cell, compensation) {
78
78
  // Remove 2 dashes per ideographic space (both are 2 cols visually)
79
79
  const dashesToRemove = compensation * 2;
80
80
  const newDashes = dashes.length > dashesToRemove ? dashes.slice(0, -dashesToRemove) : dashes;
81
+ // Also remove trailing spaces to maintain column width
82
+ const spacesToRemove = compensation * 2;
83
+ const newTrailingSpace = trailingSpace.length > spacesToRemove ? trailingSpace.slice(spacesToRemove) : "";
81
84
 
82
- return leadingSpace + leftColon + newDashes + IDEOGRAPHIC_SPACE.repeat(compensation) + rightColon + trailingSpace;
85
+ return leadingSpace + leftColon + newDashes + IDEOGRAPHIC_SPACE.repeat(compensation) + rightColon + newTrailingSpace;
83
86
  }
84
87
 
85
88
  /** Split cell into [leadingSpace, content, trailingSpace] without regex (ReDoS-safe) */
@@ -124,25 +127,53 @@ export function buildTableRow(cells) {
124
127
  return "|" + cells.join("|") + "|";
125
128
  }
126
129
 
130
+ /** Count ideographic spaces in a string */
131
+ export function countIdeographicSpaces(str) {
132
+ return (str.match(/\u3000/g) || []).length;
133
+ }
134
+
127
135
  /** Process a complete table, applying emoji compensation to all rows */
128
136
  export function processTable(tableRows) {
129
- // Strip existing ideographic spaces to start fresh
130
- const cleanedRows = tableRows.map(stripIdeographicSpaces);
131
- const parsedRows = cleanedRows.map(parseTableRow);
137
+ // Parse original rows to count existing ideographic spaces
138
+ const originalParsedRows = tableRows.map(parseTableRow);
139
+
140
+ // Normalize for emoji counting (but we'll use original cells when adequate)
141
+ const cleanedRows = tableRows.map(normalizeIdeographicSpaces);
142
+ const cleanedParsedRows = cleanedRows.map(parseTableRow);
132
143
 
133
144
  // Check if table has any emoji
134
145
  const hasEmoji = cleanedRows.some((row) => countEmoji(row) > 0);
135
- if (!hasEmoji || parsedRows.length < 2) {
146
+ if (!hasEmoji || cleanedParsedRows.length < 2) {
136
147
  return cleanedRows;
137
148
  }
138
149
 
139
- const numCols = Math.max(...parsedRows.map((r) => r.length));
140
- const maxEmojiPerCol = calculateMaxEmojiPerColumn(parsedRows, numCols);
150
+ const numCols = Math.max(...cleanedParsedRows.map((r) => r.length));
151
+ const maxEmojiPerCol = calculateMaxEmojiPerColumn(cleanedParsedRows, numCols);
141
152
 
142
153
  // Rebuild all rows with compensation
143
- return parsedRows.map((row, rowIdx) => {
154
+ return originalParsedRows.map((originalRow, rowIdx) => {
155
+ const cleanedRow = cleanedParsedRows[rowIdx];
144
156
  const isSeparatorRow = rowIdx === 1;
145
- const processedCells = row.map((cell, col) => processCell(cell, col, isSeparatorRow, maxEmojiPerCol));
157
+
158
+ const processedCells = originalRow.map((originalCell, col) => {
159
+ const cleanedCell = cleanedRow[col];
160
+ const existingCompensation = countIdeographicSpaces(originalCell);
161
+ const maxEmoji = maxEmojiPerCol[col] || 0;
162
+ const cellEmoji = countEmoji(cleanedCell);
163
+ const neededCompensation = maxEmoji - cellEmoji;
164
+
165
+ // If existing compensation is adequate, keep original cell
166
+ if (existingCompensation >= neededCompensation) {
167
+ return originalCell;
168
+ }
169
+
170
+ // Need more compensation - use normalized cell and add what's needed
171
+ const additionalCompensation = neededCompensation - existingCompensation;
172
+ return isSeparatorRow
173
+ ? compensateSeparatorCell(cleanedCell, additionalCompensation)
174
+ : compensateRegularCell(cleanedCell, additionalCompensation);
175
+ });
176
+
146
177
  return buildTableRow(processedCells);
147
178
  });
148
179
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fix-md-tables",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Fix markdown table alignment for emoji using ideographic spaces",
5
5
  "type": "module",
6
6
  "bin": {