Add code style

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
jpirnay
2026-04-23 21:36:31 +02:00
co-authored by Copilot
parent 01a9d7cb36
commit 35735b5175
9 changed files with 61 additions and 27 deletions
+35 -9
View File
@@ -11,6 +11,8 @@ static EpdFontFamily::Style combineFlags(bool bold, bool italic) {
return EpdFontFamily::REGULAR;
}
static constexpr int TAB_WIDTH = 4;
static std::string trimLeft(const std::string& s) {
size_t i = 0;
while (i < s.size() && (s[i] == ' ' || s[i] == '\t')) i++;
@@ -61,6 +63,9 @@ std::vector<Span> parseInline(const std::string& text) {
}
};
char boldMarker = 0;
char italicMarker = 0;
while (i < text.size()) {
char c = text[i];
@@ -74,7 +79,7 @@ std::vector<Span> parseInline(const std::string& text) {
}
}
// *** or ___ — toggle both bold and italic
// *** or ___ — toggle both bold and italic when marker matches the current open markers
if ((c == '*' || c == '_') && i + 2 < text.size() && text[i + 1] == c && text[i + 2] == c) {
if (c == '_' && !isUnderscoreEmphasis(text, i, 3)) {
current.append(3, c);
@@ -82,8 +87,17 @@ std::vector<Span> parseInline(const std::string& text) {
continue;
}
emitSpan();
bold = !bold;
italic = !italic;
if (bold && italic && boldMarker == c && italicMarker == c) {
bold = false;
italic = false;
boldMarker = 0;
italicMarker = 0;
} else {
bold = true;
italic = true;
boldMarker = c;
italicMarker = c;
}
i += 3;
continue;
}
@@ -96,7 +110,13 @@ std::vector<Span> parseInline(const std::string& text) {
continue;
}
emitSpan();
bold = !bold;
if (bold && boldMarker == c) {
bold = false;
boldMarker = 0;
} else {
bold = true;
boldMarker = c;
}
i += 2;
continue;
}
@@ -109,7 +129,13 @@ std::vector<Span> parseInline(const std::string& text) {
continue;
}
emitSpan();
italic = !italic;
if (italic && italicMarker == c) {
italic = false;
italicMarker = 0;
} else {
italic = true;
italicMarker = c;
}
i += 1;
continue;
}
@@ -190,9 +216,9 @@ static std::string handleTaskList(const std::string& content, std::string& listP
if (content.size() >= 3 && content[0] == '[' && content[2] == ']') {
char mark = content[1];
if (mark == 'x' || mark == 'X') {
listPrefix = "[x] ";
listPrefix = " ";
} else if (mark == ' ') {
listPrefix = "[ ] ";
listPrefix = " ";
} else {
return content; // Not a checkbox — keep content as-is
}
@@ -229,11 +255,11 @@ ParsedLine parseLine(const std::string& rawLine, bool inCodeBlock) {
if (rawLine[i] == ' ')
leadingSpaces++;
else if (rawLine[i] == '\t')
leadingSpaces += 2; // Treat tab as 2 spaces
leadingSpaces += TAB_WIDTH; // Treat tab as 4 spaces to match CommonMark nesting rules
else
break;
}
result.indentLevel = static_cast<uint8_t>(leadingSpaces / 2);
result.indentLevel = static_cast<uint8_t>(leadingSpaces / TAB_WIDTH);
std::string trimmed = trimLeft(rawLine);
+2 -2
View File
@@ -27,10 +27,10 @@ enum class BlockType : uint8_t {
};
struct ParsedLine {
BlockType blockType;
BlockType blockType = BlockType::Paragraph;
std::vector<Span> spans;
std::string listPrefix; // "• " or "1. " etc.
uint8_t indentLevel = 0; // Nesting depth (each 2 spaces = 1 level)
uint8_t indentLevel = 0; // Nesting depth (each 4 spaces = 1 level)
};
// Parse a single raw line of markdown into block type and styled spans.
+1 -1
View File
@@ -40,7 +40,7 @@ std::string Txt::getTitle() const {
size_t lastSlash = filepath.find_last_of('/');
std::string filename = (lastSlash != std::string::npos) ? filepath.substr(lastSlash + 1) : filepath;
// Remove .txt or .mdextension
// Remove .txt or .md extension
if (FsHelpers::hasTxtExtension(filename)) {
filename = filename.substr(0, filename.length() - 4);
} else if (FsHelpers::hasMarkdownExtension(filename)) {
+2 -4
View File
@@ -27,6 +27,7 @@ class MdReaderActivity final : public Activity {
std::vector<MdParser::Span> spans;
int indent = 0; // left indent in pixels
bool isHR = false; // draw as horizontal rule
bool isCodeBlock = false;
};
// Streaming reader state
@@ -71,14 +72,11 @@ class MdReaderActivity final : public Activity {
void assignHeadingPageNumbers();
int getHeadingIndexForOffset(size_t offset) const;
void jumpToHeading(bool next);
void scanHeadings();
int getHeadingIndexForOffset(size_t offset) const;
void jumpToHeading(bool next);
// Word-wrap a parsed markdown line into one or more RenderedLines.
// Returns true if all content was emitted, false if truncated by maxLines.
bool wordWrapParsedLine(const MdParser::ParsedLine& parsed, int indent, std::vector<RenderedLine>& outLines,
int maxLines);
int maxLines, bool isCodeBlock = false);
// Measure total pixel width of a span list
int measureSpans(const std::vector<MdParser::Span>& spans) const;
+12 -3
View File
@@ -320,7 +320,7 @@ int MdReaderActivity::measureSpans(const std::vector<MdParser::Span>& spans) con
}
bool MdReaderActivity::wordWrapParsedLine(const MdParser::ParsedLine& parsed, int indent,
std::vector<RenderedLine>& outLines, int maxLines) {
std::vector<RenderedLine>& outLines, int maxLines, bool isCodeBlock) {
const size_t startSize = outLines.size();
if (parsed.spans.empty()) {
@@ -347,6 +347,7 @@ bool MdReaderActivity::wordWrapParsedLine(const MdParser::ParsedLine& parsed, in
RenderedLine rl;
rl.spans = std::move(allSpans);
rl.indent = indent;
rl.isCodeBlock = isCodeBlock;
outLines.push_back(std::move(rl));
return true;
}
@@ -354,6 +355,7 @@ bool MdReaderActivity::wordWrapParsedLine(const MdParser::ParsedLine& parsed, in
// Word-wrap across spans
RenderedLine currentLine;
currentLine.indent = indent;
currentLine.isCodeBlock = isCodeBlock;
int currentWidth = 0;
bool fullyConsumed = true;
@@ -423,6 +425,7 @@ bool MdReaderActivity::wordWrapParsedLine(const MdParser::ParsedLine& parsed, in
outLines.push_back(std::move(currentLine));
currentLine = RenderedLine();
currentLine.indent = indent;
currentLine.isCodeBlock = isCodeBlock;
currentWidth = 0;
size_t skip = breakPos;
@@ -539,7 +542,8 @@ bool MdReaderActivity::loadPageAtOffset(size_t offset, bool startInCodeBlock, st
if (!wasFence) {
size_t linesBefore = outLines.size();
int remainingLines = linesPerPage - static_cast<int>(outLines.size());
bool fullyConsumed = wordWrapParsedLine(parsed, indent, outLines, remainingLines);
bool fullyConsumed = wordWrapParsedLine(parsed, indent, outLines, remainingLines,
parsed.blockType == MdParser::BlockType::CodeBlock);
if (!fullyConsumed) {
if (linesBefore > 0) {
@@ -660,7 +664,12 @@ void MdReaderActivity::renderPage() {
// Draw horizontal rule as a thin line
int hrY = y + lineHeight / 2;
renderer.drawLine(cachedOrientedMarginLeft + line.indent, hrY, cachedOrientedMarginLeft + viewportWidth, hrY);
} else if (!line.spans.empty()) {
} else {
if (line.isCodeBlock) {
const int barX = cachedOrientedMarginLeft + std::max(line.indent - 6, 0);
renderer.drawLine(barX, y + 2, barX, y + lineHeight - 2);
}
if (!line.spans.empty()) {
int x = cachedOrientedMarginLeft + line.indent;
// Apply text alignment for non-indented lines
@@ -1,10 +1,10 @@
#include "MdReaderTocSelectionActivity.h"
#include <algorithm>
#include <GfxRenderer.h>
#include <I18n.h>
#include <algorithm>
#include "components/UITheme.h"
#include "fontIds.h"
@@ -99,7 +99,8 @@ void MdReaderTocSelectionActivity::render(RenderLock&&) {
const auto& heading = headings[itemIndex];
const int indentSize = contentRect.x + 20 + (heading.level - 1) * 10;
const std::string title = renderer.truncatedText(UI_10_FONT_ID, heading.title.c_str(), contentRect.width - 40 - indentSize);
const std::string title =
renderer.truncatedText(UI_10_FONT_ID, heading.title.c_str(), contentRect.width - 40 - indentSize);
renderer.drawText(UI_10_FONT_ID, indentSize, displayY, title.c_str(), !isSelected);
}
@@ -2,8 +2,8 @@
#include <vector>
#include "MdReaderActivity.h"
#include "../Activity.h"
#include "MdReaderActivity.h"
#include "util/ButtonNavigator.h"
class MdReaderTocSelectionActivity final : public Activity {
@@ -16,7 +16,7 @@ class MdReaderTocSelectionActivity final : public Activity {
public:
explicit MdReaderTocSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
std::vector<MdHeading> headings, int currentHeadingIndex)
std::vector<MdHeading> headings, int currentHeadingIndex)
: Activity("MdReaderTocSelection", renderer, mappedInput), headings(std::move(headings)), selectorIndex(0) {
if (currentHeadingIndex >= 0 && currentHeadingIndex < static_cast<int>(headings.size())) {
selectorIndex = currentHeadingIndex;
+2 -2
View File
@@ -49,7 +49,7 @@ bool ReaderActivity::isXtcFile(const std::string& path) { return FsHelpers::hasX
bool ReaderActivity::isTxtFile(const std::string& path) { return FsHelpers::hasTxtExtension(path); }
bool ReaderActivity::isMDFile(const std::string& path) { return FsHelpers::hasMarkdownExtension(path); }
bool ReaderActivity::isMdFile(const std::string& path) { return FsHelpers::hasMarkdownExtension(path); }
bool ReaderActivity::isImageFile(const std::string& path) {
return FsHelpers::hasBmpExtension(path) || FsHelpers::hasJpgExtension(path) || FsHelpers::hasPngExtension(path);
@@ -167,7 +167,7 @@ void ReaderActivity::onEnter() {
return;
}
onGoToXtcReader(std::move(xtc));
} else if (isMDFile(initialBookPath)) {
} else if (isMdFile(initialBookPath)) {
auto txt = loadTxt(initialBookPath);
if (!txt) {
onGoBack();
+1 -1
View File
@@ -16,7 +16,7 @@ class ReaderActivity final : public Activity {
static std::unique_ptr<Txt> loadTxt(const std::string& path);
static bool isXtcFile(const std::string& path);
static bool isTxtFile(const std::string& path);
static bool isMDFile(const std::string& path);
static bool isMdFile(const std::string& path);
static bool isImageFile(const std::string& path);
static std::string extractFolderPath(const std::string& filePath);