diagrams: render mermaid as PNG instead of SVG
Qt's SVG renderer doesn't support CSS class-based styling that mermaid generates (<style> blocks with class selectors). This caused text and connectors to be invisible — they had no fill/stroke applied. Fix: output PNG from mmdc for mermaid diagrams. Qt renders PNG perfectly. PlantUML and Draw.io continue using SVG (they use inline styles).
This commit is contained in:
parent
3b27bccdda
commit
a598d0c5cc
|
|
@ -880,16 +880,19 @@ QString ChatBlockModel::diagramUrl(const QString &source, const QString &languag
|
|||
QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
|
||||
+ QStringLiteral("/diagrams");
|
||||
QDir().mkpath(cacheDir);
|
||||
QString svgPath = cacheDir + "/" + QString::fromLatin1(hash) + ".svg";
|
||||
// Mermaid uses PNG (Qt's SVG renderer can't handle CSS class-based styles);
|
||||
// PlantUML and Draw.io use SVG (inline styles, Qt-compatible).
|
||||
QString ext = (lang == QStringLiteral("mermaid")) ? QStringLiteral(".png") : QStringLiteral(".svg");
|
||||
QString outPath = cacheDir + "/" + QString::fromLatin1(hash) + ext;
|
||||
|
||||
// Return cached result if available
|
||||
if (QFileInfo::exists(svgPath))
|
||||
return QUrl::fromLocalFile(svgPath).toString();
|
||||
if (QFileInfo::exists(outPath))
|
||||
return QUrl::fromLocalFile(outPath).toString();
|
||||
|
||||
if (lang == QStringLiteral("plantuml")) {
|
||||
// Try local PlantUML server first (localhost:8080)
|
||||
if (fetchFromPlantUmlServer(source, svgPath))
|
||||
return QUrl::fromLocalFile(svgPath).toString();
|
||||
if (fetchFromPlantUmlServer(source, outPath))
|
||||
return QUrl::fromLocalFile(outPath).toString();
|
||||
|
||||
// Fall back to CLI
|
||||
QTemporaryFile input;
|
||||
|
|
@ -937,16 +940,16 @@ QString ChatBlockModel::diagramUrl(const QString &source, const QString &languag
|
|||
return QString();
|
||||
|
||||
// plantuml names output after input file, rename if needed
|
||||
if (!QFileInfo::exists(svgPath)) {
|
||||
if (!QFileInfo::exists(outPath)) {
|
||||
QString baseName = QFileInfo(input.fileName()).completeBaseName();
|
||||
QString actualOutput = cacheDir + "/" + baseName + ".svg";
|
||||
if (QFileInfo::exists(actualOutput))
|
||||
QFile::rename(actualOutput, svgPath);
|
||||
QFile::rename(actualOutput, outPath);
|
||||
}
|
||||
} else if (lang == QStringLiteral("mermaid")) {
|
||||
// Mermaid — try local server first (localhost:8081), fall back to mmdc CLI
|
||||
if (fetchFromMermaidServer(source, svgPath))
|
||||
return QUrl::fromLocalFile(svgPath).toString();
|
||||
// Note: server returns SVG which Qt can't render (CSS classes), so skip it
|
||||
// and always use CLI with PNG output for Qt compatibility.
|
||||
|
||||
QTemporaryFile input;
|
||||
input.setFileTemplate(QStringLiteral("/tmp/ollie-diagram-XXXXXX.mmd"));
|
||||
|
|
@ -965,7 +968,7 @@ QString ChatBlockModel::diagramUrl(const QString &source, const QString &languag
|
|||
proc.setProcessChannelMode(QProcess::MergedChannels);
|
||||
proc.start(mmdc, {
|
||||
QStringLiteral("-i"), input.fileName(),
|
||||
QStringLiteral("-o"), svgPath,
|
||||
QStringLiteral("-o"), outPath,
|
||||
QStringLiteral("-t"), QStringLiteral("default"),
|
||||
QStringLiteral("-b"), QStringLiteral("white")
|
||||
});
|
||||
|
|
@ -998,7 +1001,7 @@ QString ChatBlockModel::diagramUrl(const QString &source, const QString &languag
|
|||
if (reply->isFinished() && reply->error() == QNetworkReply::NoError) {
|
||||
QByteArray svg = reply->readAll();
|
||||
if (!svg.isEmpty() && svg.contains("<svg")) {
|
||||
QFile out(svgPath);
|
||||
QFile out(outPath);
|
||||
if (out.open(QIODevice::WriteOnly)) {
|
||||
out.write(svg);
|
||||
serverOk = true;
|
||||
|
|
@ -1026,7 +1029,7 @@ QString ChatBlockModel::diagramUrl(const QString &source, const QString &languag
|
|||
proc.start(drawio, {
|
||||
QStringLiteral("--export"),
|
||||
QStringLiteral("--format"), QStringLiteral("svg"),
|
||||
QStringLiteral("--output"), svgPath,
|
||||
QStringLiteral("--output"), outPath,
|
||||
input.fileName()
|
||||
});
|
||||
|
||||
|
|
@ -1035,10 +1038,10 @@ QString ChatBlockModel::diagramUrl(const QString &source, const QString &languag
|
|||
}
|
||||
}
|
||||
|
||||
if (!QFileInfo::exists(svgPath))
|
||||
if (!QFileInfo::exists(outPath))
|
||||
return QString();
|
||||
|
||||
return QUrl::fromLocalFile(svgPath).toString();
|
||||
return QUrl::fromLocalFile(outPath).toString();
|
||||
}
|
||||
|
||||
bool ChatBlockModel::invalidateDiagram(const QString &source, const QString &language) const
|
||||
|
|
@ -1053,7 +1056,8 @@ bool ChatBlockModel::invalidateDiagram(const QString &source, const QString &lan
|
|||
(lang + "\x1f" + source).toUtf8(), QCryptographicHash::Sha256).toHex().left(16);
|
||||
QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
|
||||
+ QStringLiteral("/diagrams");
|
||||
QString svgPath = cacheDir + "/" + QString::fromLatin1(hash) + ".svg";
|
||||
QString ext = (lang == QStringLiteral("mermaid")) ? QStringLiteral(".png") : QStringLiteral(".svg");
|
||||
QString outPath = cacheDir + "/" + QString::fromLatin1(hash) + ext;
|
||||
|
||||
return QFile::remove(svgPath);
|
||||
return QFile::remove(outPath);
|
||||
}
|
||||
|
|
|
|||
Reference in New Issue