История: diff прямо в Просмотре версии + код не в одну строку
- Подсветка: highlight() отдаёт <br/> вместо сырых \n (RichText их схлопывал — код был одной строкой); plainToRich для fallback-путей - MdParser.parseBlocksWithDiff(old,new): поблочный LCS-diff с fence-aware разбивкой, change same/del/add, изменённые блоки в цветном div (красный/зелёный как в diff), codeId для копирования сохранены - MarkdownView.compareMarkdown: при задании рендерит версию с подсветкой отличий - История: Просмотр версии сравнивается со свежим содержимым с диска (workdirContent), легенда на обеих вкладках - Тесты: <br/>, порядок del/add, тинты, identical без подсветки
This commit is contained in:
@@ -134,6 +134,55 @@ int main(int argc, char *argv[])
|
||||
if (!hl2.contains("span")) return fail("hl2 no span", hl2.left(200));
|
||||
}
|
||||
|
||||
// Подсветка: переносы строк — явные <br/>, иначе RichText склеит в одну строку
|
||||
{
|
||||
QString hl = p.highlightedCode("int a = 1;\nint b = 2;\n", "cpp");
|
||||
if (!hl.contains("<br/>")) return fail("highlighted без <br/>", hl.left(200));
|
||||
if (hl.contains("\n")) return fail("highlighted с сырым \\n", hl.left(200));
|
||||
QString plain = p.highlightedCode("a\nb", "неизвестный-язык-xyz");
|
||||
if (!plain.contains("<br/>")) return fail("plain highlight без <br/>", plain);
|
||||
}
|
||||
|
||||
// parseBlocksWithDiff: версия old vs текущее new
|
||||
{
|
||||
const QString oldMd = "# Заголовок\n\nСтарая строка\n\n```cpp\nint x = 1;\n```\n";
|
||||
const QString newMd = "# Заголовок\n\nНовая строка\n\n```cpp\nint x = 2;\n```\n";
|
||||
auto d = p.parseBlocksWithDiff(oldMd, newMd, vault, fileDir);
|
||||
if (d.isEmpty()) return fail("diff пуст");
|
||||
// порядок как у стандартного diff: сначала все del изменённого куска, потом все add
|
||||
auto changeOf = [&](int i) { return d[i].toMap().value("change").toString(); };
|
||||
if (d.size() != 5) return fail("diff размер", QString::number(d.size()));
|
||||
if (changeOf(0) != "same") return fail("diff[0] должен быть same", changeOf(0));
|
||||
if (d[0].toMap().value("type").toString() != "html") return fail("diff[0] тип");
|
||||
if (changeOf(1) != "del") return fail("diff[1] должен быть del", changeOf(1));
|
||||
if (!d[1].toMap().value("html").toString().contains("ffebe9")) return fail("diff[1] без красной подсветки");
|
||||
if (changeOf(2) != "del" || d[2].toMap().value("type").toString() != "code")
|
||||
return fail("diff[2] код del", changeOf(2));
|
||||
if (!d[2].toMap().value("highlightedText").toString().contains("ffebe9"))
|
||||
return fail("diff[2] код без красной подсветки");
|
||||
if (changeOf(3) != "add") return fail("diff[3] должен быть add", changeOf(3));
|
||||
if (!d[3].toMap().value("html").toString().contains("e6ffec")) return fail("diff[3] без зелёной подсветки");
|
||||
if (changeOf(4) != "add" || d[4].toMap().value("type").toString() != "code")
|
||||
return fail("diff[4] код add", changeOf(4));
|
||||
// кодовые блоки сохранили id для копирования
|
||||
if (d[2].toMap().value("codeId").toString().isEmpty()) return fail("diff codeId пуст");
|
||||
if (p.getCodeBlock(d[2].toMap().value("codeId").toString()) != "int x = 1;")
|
||||
return fail("getCodeBlock после diff", p.getCodeBlock(d[2].toMap().value("codeId").toString()));
|
||||
}
|
||||
|
||||
// parseBlocksWithDiff: идентичные тексты — всё same, без подсветки
|
||||
{
|
||||
const QString md = "# A\n\ntext\n";
|
||||
auto d = p.parseBlocksWithDiff(md, md, vault, fileDir);
|
||||
for (const auto &v : d) {
|
||||
if (v.toMap().value("change").toString() != "same")
|
||||
return fail("identical должен быть same");
|
||||
if (v.toMap().value("html").toString().contains("ffebe9")
|
||||
|| v.toMap().value("html").toString().contains("e6ffec"))
|
||||
return fail("identical с подсветкой");
|
||||
}
|
||||
}
|
||||
|
||||
std::printf("MDPARSER TEST OK\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user