mdview: fix fenced code block emphasis leak and carry emphasis across wrap lines
- Add fenced code block tracking to the wrap-pass in index_lines(). line_style is reset to PLAIN at every ``` delimiter, and all segs inside a fenced block get init_style=PLAIN. This prevents emphasis markers (e.g. _ in __var) inside code blocks from leaking into later normal text. - Also carry init_style across wrap continuation segs so that a long bold/italic line that is wrapped continues with the correct style on the next segment. - The fence bitmap pass now only updates in_code[], since init_style is already set correctly by the wrap pass.
This commit is contained in:
@@ -551,15 +551,25 @@ static void index_lines(void)
|
|||||||
} else {
|
} else {
|
||||||
/* Wrap: walk logical lines, split each into one or more segs. */
|
/* Wrap: walk logical lines, split each into one or more segs. */
|
||||||
uint32_t p = 0;
|
uint32_t p = 0;
|
||||||
|
uint8_t in_block = 0; /* inside fenced code block? */
|
||||||
line_style = INIT_STYLE_PLAIN;
|
line_style = INIT_STYLE_PLAIN;
|
||||||
while (p < file_size && n_lines < MAX_LINES) {
|
while (p < file_size && n_lines < MAX_LINES) {
|
||||||
set_init_style_raw(n_lines, line_style);
|
|
||||||
if ((n_lines & 15) == 0) spinner_tick();
|
if ((n_lines & 15) == 0) spinner_tick();
|
||||||
/* Find end of logical line (\n or EOF). */
|
/* Find end of logical line (\n or EOF). */
|
||||||
uint32_t line_end = p;
|
uint32_t line_end = p;
|
||||||
while (line_end < file_size && fb(line_end) != '\n') line_end++;
|
while (line_end < file_size && fb(line_end) != '\n') line_end++;
|
||||||
|
|
||||||
|
/* Detect fenced-code delimiter (``` at col 0). Toggle in_block
|
||||||
|
* and reset emphasis tracking — code blocks never carry inline
|
||||||
|
* style across their boundaries. */
|
||||||
|
if (p + 2 < file_size &&
|
||||||
|
fb(p) == '`' && fb(p + 1) == '`' && fb(p + 2) == '`') {
|
||||||
|
in_block = (uint8_t)!in_block;
|
||||||
|
line_style = INIT_STYLE_PLAIN;
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit the first seg of this logical line (no CONT). */
|
/* Emit the first seg of this logical line (no CONT). */
|
||||||
|
set_init_style_raw(n_lines, in_block ? INIT_STYLE_PLAIN : line_style);
|
||||||
line_offset[n_lines++] = p;
|
line_offset[n_lines++] = p;
|
||||||
|
|
||||||
if (!is_nowrap_line(p)) {
|
if (!is_nowrap_line(p)) {
|
||||||
@@ -579,6 +589,37 @@ static void index_lines(void)
|
|||||||
char prev_ch = ' '; /* for emphasis flanking */
|
char prev_ch = ' '; /* for emphasis flanking */
|
||||||
while (q < line_end && n_lines < MAX_LINES) {
|
while (q < line_end && n_lines < MAX_LINES) {
|
||||||
char ch = fb(q);
|
char ch = fb(q);
|
||||||
|
/* Inside fenced code block: every byte is literal, no
|
||||||
|
* emphasis markers, but wrap still applies. */
|
||||||
|
if (in_block) {
|
||||||
|
if (ch == '\t') {
|
||||||
|
uint8_t tgt = (uint8_t)((col & (uint8_t)~(TAB_STOP - 1)) + TAB_STOP);
|
||||||
|
if (tgt > SCREEN_W) tgt = SCREEN_W;
|
||||||
|
col = tgt;
|
||||||
|
q++;
|
||||||
|
prev_ch = ' ';
|
||||||
|
} else {
|
||||||
|
if (ch == ' ') last_space = q + 1;
|
||||||
|
col++;
|
||||||
|
q++;
|
||||||
|
prev_ch = ch;
|
||||||
|
}
|
||||||
|
if (col >= SCREEN_W && q < line_end) {
|
||||||
|
uint32_t wrap_at = (last_space != 0xFFFFFFFFu &&
|
||||||
|
last_space > line_offset[n_lines - 1])
|
||||||
|
? last_space : q;
|
||||||
|
if (wrap_at >= line_end) break;
|
||||||
|
line_offset[n_lines] = wrap_at;
|
||||||
|
set_init_style_raw(n_lines, INIT_STYLE_PLAIN);
|
||||||
|
set_cont(n_lines);
|
||||||
|
n_lines++;
|
||||||
|
col = 0;
|
||||||
|
last_space = 0xFFFFFFFFu;
|
||||||
|
prev_ch = ' ';
|
||||||
|
q = wrap_at;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* Backtick — always zero-width (inline code delimiter). */
|
/* Backtick — always zero-width (inline code delimiter). */
|
||||||
if (ch == '`') {
|
if (ch == '`') {
|
||||||
q++;
|
q++;
|
||||||
@@ -598,7 +639,7 @@ static void index_lines(void)
|
|||||||
line_style = INIT_STYLE_PLAIN;
|
line_style = INIT_STYLE_PLAIN;
|
||||||
q += 2;
|
q += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
col += 2;
|
col += 2;
|
||||||
q += 2;
|
q += 2;
|
||||||
@@ -618,7 +659,7 @@ static void index_lines(void)
|
|||||||
line_style = INIT_STYLE_PLAIN;
|
line_style = INIT_STYLE_PLAIN;
|
||||||
q++;
|
q++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
col++;
|
col++;
|
||||||
q++;
|
q++;
|
||||||
@@ -642,6 +683,7 @@ static void index_lines(void)
|
|||||||
? last_space : q;
|
? last_space : q;
|
||||||
if (wrap_at >= line_end) break;
|
if (wrap_at >= line_end) break;
|
||||||
line_offset[n_lines] = wrap_at;
|
line_offset[n_lines] = wrap_at;
|
||||||
|
set_init_style_raw(n_lines, line_style); /* carry style across wrap */
|
||||||
set_cont(n_lines);
|
set_cont(n_lines);
|
||||||
n_lines++;
|
n_lines++;
|
||||||
col = 0;
|
col = 0;
|
||||||
@@ -656,18 +698,19 @@ static void index_lines(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fence/code-body bitmap pass — only non-CONT segs participate. */
|
/* Fence/code-body bitmap pass — only non-CONT segs participate.
|
||||||
|
* The wrap-pass above already tracked fenced blocks and set init_style
|
||||||
|
* to PLAIN for every seg inside; this pass only fixes the in_code[]
|
||||||
|
* bitmap (used by render_line to disable inline parsing). */
|
||||||
{
|
{
|
||||||
uint8_t in_block = 0;
|
uint8_t in_block = 0;
|
||||||
for (uint16_t i = 0; i < n_lines; i++) {
|
for (uint16_t i = 0; i < n_lines; i++) {
|
||||||
if (is_cont(i)) {
|
if (is_cont(i)) {
|
||||||
if(is_code_body(i - 1)) {
|
if (is_code_body(i - 1)) {
|
||||||
in_code[i >> 3] |= (uint8_t)(1u << (i & 7));
|
in_code[i >> 3] |= (uint8_t)(1u << (i & 7));
|
||||||
set_init_style_raw(i, INIT_STYLE_PLAIN);
|
set_init_style_raw(i, INIT_STYLE_PLAIN);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (is_fence_delim(i)) {
|
if (is_fence_delim(i)) {
|
||||||
in_block = (uint8_t)!in_block;
|
in_block = (uint8_t)!in_block;
|
||||||
|
|||||||
Reference in New Issue
Block a user