Исправлен белый экран предпросмотра: CodeBlock отдельный компонент
- CodeBlock.qml: Qt.rgba вместо "rgba(...)", убран lineHeight, contentHeight для ScrollView, width via availableWidth - MarkdownView.qml: ListModel с полными ролями (codeText/highlightedText), delegate без required model, Column anchors.top/left/right, parseBlocks сохраняет codeBlocks - MdParser: parseBlocks с QRegularExpression и сохранением codeBlocks, forceDark highlight - mdparser_test: проверка parseBlocks 3 блока - ctest 21/21, offscreen/cocoa RUNNING OK, Flora.app 180М
This commit is contained in:
@@ -100,10 +100,11 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
color: Qt.rgba(0,0,0,0.22)
|
color: Qt.rgba(0,0,0,0.22)
|
||||||
radius: 8
|
radius: 8
|
||||||
// height based on content
|
// height based on content - use contentHeight for accurate
|
||||||
implicitHeight: codeText.implicitHeight + 20
|
implicitHeight: Math.max(40, codeText.contentHeight + 20)
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
id: codeScroll
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 8
|
anchors.margins: 8
|
||||||
clip: true
|
clip: true
|
||||||
@@ -112,6 +113,7 @@ Rectangle {
|
|||||||
|
|
||||||
TextArea {
|
TextArea {
|
||||||
id: codeText
|
id: codeText
|
||||||
|
width: codeScroll.availableWidth
|
||||||
readOnly: true
|
readOnly: true
|
||||||
selectByMouse: true
|
selectByMouse: true
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
@@ -124,6 +126,10 @@ Rectangle {
|
|||||||
tabStopDistance: 32
|
tabStopDistance: 32
|
||||||
text: root.highlightedText.length > 0 ? root.highlightedText : root.code
|
text: root.highlightedText.length > 0 ? root.highlightedText : root.code
|
||||||
background: Rectangle { color: "transparent" }
|
background: Rectangle { color: "transparent" }
|
||||||
|
// Ensure contentHeight is updated
|
||||||
|
onTextChanged: {
|
||||||
|
// Force update
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,14 +43,16 @@ Item {
|
|||||||
Repeater {
|
Repeater {
|
||||||
model: blocksModel
|
model: blocksModel
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
|
required property var model
|
||||||
|
required property int index
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
property string blockType: model.type || ""
|
property string blockType: model.type || ""
|
||||||
property string blockHtml: model.html || ""
|
property string blockHtml: model.html || ""
|
||||||
property string blockCode: model.code || ""
|
property string blockCode: model.codeText || ""
|
||||||
property string blockLang: model.language || "text"
|
property string blockLang: model.language || "text"
|
||||||
property string blockCodeId: model.codeId || ""
|
property string blockCodeId: model.codeId || ""
|
||||||
property string blockHighlighted: model.highlighted || ""
|
property string blockHighlighted: model.highlightedText || ""
|
||||||
// HTML block
|
// HTML block
|
||||||
Text {
|
Text {
|
||||||
visible: blockType === "html" && blockHtml
|
visible: blockType === "html" && blockHtml
|
||||||
|
|||||||
@@ -768,8 +768,16 @@ QVariantList MdParser::parseBlocks(const QString &markdown, const QString &vault
|
|||||||
if (m) { savedBlocks = m->codeBlocks; savedCounter = m->codeCounter; }
|
if (m) { savedBlocks = m->codeBlocks; savedCounter = m->codeCounter; }
|
||||||
QString html = render(htmlPart, vaultRoot, fileDir);
|
QString html = render(htmlPart, vaultRoot, fileDir);
|
||||||
if (m) { m->codeBlocks = savedBlocks; m->codeCounter = savedCounter; }
|
if (m) { m->codeBlocks = savedBlocks; m->codeCounter = savedCounter; }
|
||||||
if (!html.trimmed().isEmpty())
|
if (!html.trimmed().isEmpty()) {
|
||||||
blocks.append(QVariantMap{{"type", "html"}, {"html", html}});
|
QVariantMap block;
|
||||||
|
block["type"] = "html";
|
||||||
|
block["html"] = html;
|
||||||
|
block["codeText"] = "";
|
||||||
|
block["language"] = "";
|
||||||
|
block["codeId"] = "";
|
||||||
|
block["highlightedText"] = "";
|
||||||
|
blocks.append(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QString langRaw = match.captured(1).trimmed();
|
QString langRaw = match.captured(1).trimmed();
|
||||||
@@ -789,10 +797,11 @@ QVariantList MdParser::parseBlocks(const QString &markdown, const QString &vault
|
|||||||
}
|
}
|
||||||
QVariantMap block;
|
QVariantMap block;
|
||||||
block["type"] = "code";
|
block["type"] = "code";
|
||||||
block["code"] = code;
|
block["codeText"] = code;
|
||||||
block["language"] = lang.isEmpty() ? "text" : lang;
|
block["language"] = lang.isEmpty() ? "text" : lang;
|
||||||
block["codeId"] = codeId;
|
block["codeId"] = codeId;
|
||||||
block["highlighted"] = highlighted;
|
block["highlightedText"] = highlighted;
|
||||||
|
block["html"] = "";
|
||||||
blocks.append(block);
|
blocks.append(block);
|
||||||
lastPos = end;
|
lastPos = end;
|
||||||
}
|
}
|
||||||
@@ -805,8 +814,16 @@ QVariantList MdParser::parseBlocks(const QString &markdown, const QString &vault
|
|||||||
if (m) { savedBlocks = m->codeBlocks; savedCounter = m->codeCounter; }
|
if (m) { savedBlocks = m->codeBlocks; savedCounter = m->codeCounter; }
|
||||||
QString html = render(htmlPart, vaultRoot, fileDir);
|
QString html = render(htmlPart, vaultRoot, fileDir);
|
||||||
if (m) { m->codeBlocks = savedBlocks; m->codeCounter = savedCounter; }
|
if (m) { m->codeBlocks = savedBlocks; m->codeCounter = savedCounter; }
|
||||||
if (!html.trimmed().isEmpty())
|
if (!html.trimmed().isEmpty()) {
|
||||||
blocks.append(QVariantMap{{"type", "html"}, {"html", html}});
|
QVariantMap block;
|
||||||
|
block["type"] = "html";
|
||||||
|
block["html"] = html;
|
||||||
|
block["codeText"] = "";
|
||||||
|
block["language"] = "";
|
||||||
|
block["codeId"] = "";
|
||||||
|
block["highlightedText"] = "";
|
||||||
|
blocks.append(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Если вообще не нашли блоки, но markdown не пустой — вернём как html
|
// Если вообще не нашли блоки, но markdown не пустой — вернём как html
|
||||||
@@ -816,7 +833,14 @@ QVariantList MdParser::parseBlocks(const QString &markdown, const QString &vault
|
|||||||
if (m) { savedBlocks = m->codeBlocks; savedCounter = m->codeCounter; }
|
if (m) { savedBlocks = m->codeBlocks; savedCounter = m->codeCounter; }
|
||||||
QString html = render(markdown, vaultRoot, fileDir);
|
QString html = render(markdown, vaultRoot, fileDir);
|
||||||
if (m) { m->codeBlocks = savedBlocks; m->codeCounter = savedCounter; }
|
if (m) { m->codeBlocks = savedBlocks; m->codeCounter = savedCounter; }
|
||||||
blocks.append(QVariantMap{{"type", "html"}, {"html", html}});
|
QVariantMap block;
|
||||||
|
block["type"] = "html";
|
||||||
|
block["html"] = html;
|
||||||
|
block["codeText"] = "";
|
||||||
|
block["language"] = "";
|
||||||
|
block["codeId"] = "";
|
||||||
|
block["highlightedText"] = "";
|
||||||
|
blocks.append(block);
|
||||||
}
|
}
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-2
@@ -111,8 +111,16 @@ int main(int argc, char *argv[])
|
|||||||
if (blocks[0].toMap().value("type").toString() != "html") return fail("block 0 type", blocks[0].toMap().value("type").toString());
|
if (blocks[0].toMap().value("type").toString() != "html") return fail("block 0 type", blocks[0].toMap().value("type").toString());
|
||||||
if (blocks[1].toMap().value("type").toString() != "code") return fail("block 1 type", blocks[1].toMap().value("type").toString());
|
if (blocks[1].toMap().value("type").toString() != "code") return fail("block 1 type", blocks[1].toMap().value("type").toString());
|
||||||
if (blocks[1].toMap().value("language").toString() != "C++" && blocks[1].toMap().value("language").toString() != "cpp") return fail("block 1 lang", blocks[1].toMap().value("language").toString());
|
if (blocks[1].toMap().value("language").toString() != "C++" && blocks[1].toMap().value("language").toString() != "cpp") return fail("block 1 lang", blocks[1].toMap().value("language").toString());
|
||||||
if (!blocks[1].toMap().value("code").toString().contains("int x=1;")) return fail("block 1 code", blocks[1].toMap().value("code").toString());
|
{
|
||||||
if (blocks[1].toMap().value("highlighted").toString().isEmpty()) return fail("highlighted empty");
|
QString codeVal = blocks[1].toMap().value("codeText").toString();
|
||||||
|
if (codeVal.isEmpty()) codeVal = blocks[1].toMap().value("code").toString();
|
||||||
|
if (!codeVal.contains("int x=1;")) return fail("block 1 code", codeVal);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QString hl = blocks[1].toMap().value("highlightedText").toString();
|
||||||
|
if (hl.isEmpty()) hl = blocks[1].toMap().value("highlighted").toString();
|
||||||
|
if (hl.isEmpty()) return fail("highlighted empty");
|
||||||
|
}
|
||||||
if (blocks[2].toMap().value("type").toString() != "html") return fail("block 2 type");
|
if (blocks[2].toMap().value("type").toString() != "html") return fail("block 2 type");
|
||||||
|
|
||||||
std::printf("MDPARSER TEST OK\n");
|
std::printf("MDPARSER TEST OK\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user