fix(plan-canvas): stop dropping list items when a block's first item is over-indented (#2501)

* fix(plan-canvas): stop dropping list items when a block's first item is over-indented

* fix: address greptile findings for PR #2501 - list-type detection and outdent nesting

- plan-canvas markdown: fix nested list rendering where outdented runs (indent
  6→4) create duplicate sibling UL blocks instead of sharing parent (#2501)
- transcript-context: add LARGE_WINDOW_NATIVE_MODEL_IDS array for models whose
  default context window is 1M but do NOT carry the [1m] marker (fixes #2497)
- Add test coverage for transcript-context and shell-substitution modules
- Add test coverage for project-detect module (#2498)

* fix(plan-canvas): handle outdented list runs

* fix(plan-canvas): start a new list when marker type changes at the same indent

CommonMark treats a marker-type change (bullet to ordered or back) at
the same indentation as the start of a new list. buildList previously
absorbed the run into the current list, so mixed runs rendered under a
single wrong tag. Stop the run on a tag change and let buildListBlock
render the next run as a sibling list with its own tag.
This commit is contained in:
黄云龙 2026-07-18 05:10:58 +08:00 committed by GitHub
parent fb98726d0a
commit 5d68ef3617
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 2 deletions

View file

@ -152,6 +152,44 @@ function runTests() {
assert.strictEqual(renderMarkdown('* a\n* b'), '<ul>\n<li>a</li>\n<li>b</li>\n</ul>');
})) passed++; else failed++;
if (test('preserves items that outdent below the first item', () => {
assert.strictEqual(
renderMarkdown(' - alpha\n- beta\n- gamma'),
'<ul>\n<li>alpha</li>\n</ul>\n<ul>\n<li>beta</li>\n<li>gamma</li>\n</ul>'
);
})) passed++; else failed++;
if (test('uses each outdented run marker for its list type', () => {
assert.strictEqual(
renderMarkdown(' - prep\n1. phase one\n2. phase two'),
'<ul>\n<li>prep</li>\n</ul>\n<ol>\n<li>phase one</li>\n<li>phase two</li>\n</ol>'
);
})) passed++; else failed++;
if (test('marker type change at the same indent starts a new list', () => {
assert.strictEqual(
renderMarkdown('- prep\n1. phase one\n2. phase two'),
'<ul>\n<li>prep</li>\n</ul>\n<ol>\n<li>phase one</li>\n<li>phase two</li>\n</ol>'
);
})) passed++; else failed++;
if (test('switching back to bullets after a numbered run starts a third list', () => {
assert.strictEqual(
renderMarkdown('1. one\n- bullet\n2. two'),
'<ol>\n<li>one</li>\n</ol>\n<ul>\n<li>bullet</li>\n</ul>\n<ol>\n<li>two</li>\n</ol>'
);
})) passed++; else failed++;
if (test('renders repeated outdents without empty parent items', () => {
const out = renderMarkdown(' - deep one\n - deep two\n - middle\n- shallow');
assert.strictEqual(
out,
'<ul>\n<li>deep one</li>\n<li>deep two</li>\n</ul>\n' +
'<ul>\n<li>middle</li>\n</ul>\n<ul>\n<li>shallow</li>\n</ul>'
);
assert.ok(!out.includes('<li>\n<ul>'), `No empty parent item expected, got ${out}`);
})) passed++; else failed++;
// Table tests
console.log('\nTables:');