Skip to content

Commit 36ee215

Browse files
krotnameclaude
andauthored
Fix Markdown table core round-trip defects and release 0.2.0 (#23)
Five reproducible defects were found by property and fuzz testing of the public facade and are fixed with regression coverage: - findTableRanges could return overlapping ranges when a table was followed by a line that was itself a valid separator, so whole-document reformatting rewrote one row twice and corrupted the document. - The formatter emitted tables it could not parse back: without outer pipes, an empty edge cell produced a row ending (or starting) with a pipe that re-parsing consumed as an outer pipe, dropping a column. - Deleting down to one column in a table without outer pipes left rows with no pipe at all, turning the table into plain text. - A header made only of dashes was mistaken for the separator row, so every edit on such a table was rejected. - EditResult.changed was hardcoded to true instead of reporting whether the result differs from the input. Readability work keeps behaviour unchanged: the duplicated preamble of apply and applyWrappedToWidth moved into resolveTable, the action switch moved into applyAction, the two nearly identical wrap routines merged, the three column width helpers share one accumulator, dead code is gone, and the public Javadoc now documents the result coordinate system and the non-overlap guarantee. Testing: new MarkdownTableCoreContractTest adds 105 cases covering alignment, structural edits, sorting, navigation, wrapping, conversion, Unicode widths, argument handling, immutability, and a randomised invariant sweep; four golden fixtures pin the fixed behaviours. Core line coverage is 94%. corePerformance gains p95 reporting and an end-to-end scenario, and passed three isolated runs. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 0c16393 commit 36ee215

10 files changed

Lines changed: 1215 additions & 256 deletions

File tree

README.en.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,10 @@ You can change shortcuts in `Settings | Keymap`.
180180
## Standalone Core Library
181181

182182
The editor-independent engine is a separate Java 17 module with no runtime dependencies:
183-
[`name.krot:markdown-table-core`](core/README.md). The plugin consumes that module through the
184-
same Gradle build, so plugin tests also verify the real library integration.
183+
[`name.krot:markdown-table-core:0.2.0`](https://central.sonatype.com/artifact/name.krot/markdown-table-core/0.2.0).
184+
The plugin consumes the artifact published to Maven Central, so plugin tests verify the same
185+
public library that external consumers get. Core release notes live in
186+
[core/CHANGELOG.md](core/CHANGELOG.md).
185187

186188
## Build and Tests
187189

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,10 @@ Marketplace вычисляет конкретные версии продукт
181181
## Самостоятельная библиотека ядра
182182

183183
Независимое от редактора ядро выделено в Java 17 модуль без runtime-зависимостей:
184-
[`name.krot:markdown-table-core:0.1.0`](https://central.sonatype.com/artifact/name.krot/markdown-table-core/0.1.0).
184+
[`name.krot:markdown-table-core:0.2.0`](https://central.sonatype.com/artifact/name.krot/markdown-table-core/0.2.0).
185185
Плагин использует опубликованный артефакт из Maven Central, поэтому plugin-тесты проверяют
186186
интеграцию с той же публичной библиотекой, которую получают внешние потребители.
187+
История изменений ядра — в [core/CHANGELOG.md](core/CHANGELOG.md).
187188

188189
## Сборка и тесты
189190

core/CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Markdown Table Core changelog
2+
3+
All notable changes to `name.krot:markdown-table-core` are recorded here.
4+
The module follows [semantic versioning](https://semver.org/).
5+
6+
## 0.2.0
7+
8+
Source and binary compatible with `0.1.0`: no public type, method, field, or enum constant was
9+
removed, added, or changed. Only the observed behaviour of existing methods changed, as listed
10+
below.
11+
12+
### Fixed
13+
14+
- `findTableRanges` could return overlapping ranges when a table was directly followed by a line
15+
that was itself a valid separator. The trailing row of one table was reused as the header of the
16+
next one, so a caller that rewrote every range independently corrupted the document. Scanning
17+
now resumes past the end of each table.
18+
- The formatter could emit a table it was unable to parse back. When a table carried no outer
19+
pipes and an edge cell was empty - for example right after inserting a column into
20+
`a | b` - the padded row ended with a pipe that re-parsing consumed as an outer pipe, dropping a
21+
column and breaking header/separator agreement. Rows now keep the outer pipe whenever the first
22+
or last column contains an empty cell.
23+
- Deleting the second column of a table without outer pipes left rows with no pipe at all, turning
24+
the table into plain text. A single-column table without a leading pipe now always renders a
25+
trailing one.
26+
- A header made only of dashes, such as `| --- | --- |` above its separator, was mistaken for the
27+
separator row, and every edit on that table was rejected with `No Markdown table found`. The
28+
separator search now starts below the header.
29+
- `EditResult.changed` was always `true`. It now reports whether the returned lines actually differ
30+
from the table the operation started from, so successful no-ops such as aligning an already
31+
aligned table report `false` while `ok` stays `true`.
32+
33+
### Changed
34+
35+
- `findTableRange` stops scanning once the document is past the requested row instead of always
36+
mapping the whole document, which speeds up edits in long files.
37+
38+
### Documentation
39+
40+
- The Javadoc of `EditResult` now states that the result carries only the affected table and that
41+
`targetRow` indexes into `lines`, not into the document.
42+
- `findTableRanges` documents the non-overlap guarantee, and `apply` documents that out-of-range
43+
coordinates are clamped rather than rejected.
44+
45+
## 0.1.0
46+
47+
- First public release: parsing, formatting, conversion, and editing for GitHub-flavored Markdown
48+
pipe tables, with no runtime dependencies on Java 17.

core/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ GitHub-flavored Markdown pipe tables.
77

88
```kotlin
99
dependencies {
10-
implementation("name.krot:markdown-table-core:0.1.0")
10+
implementation("name.krot:markdown-table-core:0.2.0")
1111
}
1212
```
1313

14-
Version `0.1.0` is published on
15-
[Maven Central](https://central.sonatype.com/artifact/name.krot/markdown-table-core/0.1.0)
14+
Version `0.2.0` is published on
15+
[Maven Central](https://central.sonatype.com/artifact/name.krot/markdown-table-core/0.2.0)
1616
and available from the
17-
[Central repository](https://repo1.maven.org/maven2/name/krot/markdown-table-core/0.1.0/).
17+
[Central repository](https://repo1.maven.org/maven2/name/krot/markdown-table-core/0.2.0/).
18+
19+
See [CHANGELOG.md](CHANGELOG.md) for what changed since `0.1.0`.
1820

1921
## Usage
2022

core/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.0
1+
0.2.0

core/src/main/java/name/krot/markdowntable/core/MarkdownTableCore.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,27 @@ public enum Action {
5555

5656
/**
5757
* Immutable result of a table edit or conversion.
58+
*
59+
* <p>{@link #lines} holds only the affected table, not the whole document, and
60+
* {@link #targetRow} indexes into those lines. Callers that pass a whole document to
61+
* {@link #apply} therefore add {@link TableRange#firstRow} to map the target back onto the
62+
* document.</p>
5863
*/
5964
public static final class EditResult {
60-
/** Whether the returned text differs from the input. */
65+
/**
66+
* Whether the returned lines differ from the table the operation started from.
67+
*
68+
* <p>Successful no-ops such as aligning an already aligned table, or moving the first data
69+
* row further up, report {@code false} while {@link #ok} stays {@code true}.</p>
70+
*/
6171
public final boolean changed;
6272
/** Whether the operation completed successfully. */
6373
public final boolean ok;
6474
/** Human-readable failure or status detail; empty on normal success. */
6575
public final String message;
66-
/** Immutable formatted or converted lines. */
76+
/** Immutable formatted or converted lines; empty when {@link #ok} is {@code false}. */
6777
public final List<String> lines;
68-
/** Zero-based target row after the operation. */
78+
/** Zero-based target row within {@link #lines} after the operation. */
6979
public final int targetRow;
7080
/** Zero-based target column after the operation. */
7181
public final int targetColumn;
@@ -187,7 +197,11 @@ public static TableRange findTableRange(List<String> lines, int row) {
187197
}
188198

189199
/**
190-
* Finds all non-overlapping Markdown table ranges in document order.
200+
* Finds every Markdown table in document order.
201+
*
202+
* <p>The returned ranges are strictly ordered and never overlap, so a caller may rewrite each
203+
* one independently. Scanning resumes past the end of a table even when its last row still
204+
* carries pipes, so a trailing row is never reused as the header of the next table.</p>
191205
*
192206
* @param lines document lines
193207
* @return immutable ranges in document order
@@ -214,11 +228,16 @@ public static boolean isPotentialSeparatorLine(String line) {
214228
/**
215229
* Applies an editing action to the table containing {@code row}.
216230
*
231+
* <p>Out-of-range coordinates are clamped into the table rather than rejected. The result
232+
* carries only the rewritten table; see {@link EditResult} for how its coordinates relate to
233+
* the document.</p>
234+
*
217235
* @param lines document lines
218236
* @param row zero-based document row
219237
* @param column zero-based cell index
220238
* @param action operation to apply
221-
* @return immutable operation result
239+
* @return immutable operation result; {@link EditResult#ok} is {@code false} when {@code row}
240+
* is not inside a Markdown table
222241
*/
223242
public static EditResult apply(List<String> lines, int row, int column, Action action) {
224243
Objects.requireNonNull(action, "action");

0 commit comments

Comments
 (0)