Skip to content

Commit c035c86

Browse files
cyphercodeskermanx
andauthored
fix(client): ignore nested katex tables for line highlights (#2579)
Co-authored-by: cyphercodes <cyphercodes@users.noreply.github.com> Co-authored-by: _Kerman <kermanx@qq.com>
1 parent 5e912cb commit c035c86

3 files changed

Lines changed: 67 additions & 19 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { collectKatexEquationLines } from './katex-lines'
3+
4+
function fakeElement(options: {
5+
parent?: Element | null
6+
closest?: Element | null
7+
children?: Element[]
8+
} = {}) {
9+
const el = {
10+
parentElement: options.parent ?? null,
11+
closest: () => options.closest ?? null,
12+
querySelectorAll: () => options.children ?? [],
13+
}
14+
return el as unknown as Element
15+
}
16+
17+
describe('collectKatexEquationLines', () => {
18+
it('ignores nested KaTeX tables when mapping equation lines', () => {
19+
const rowA1 = fakeElement()
20+
const rowA2 = fakeElement()
21+
const rowB1 = fakeElement()
22+
const rowB2 = fakeElement()
23+
const nestedRow = fakeElement()
24+
25+
const outerLeftParent = fakeElement({ children: [rowA1, rowA2] })
26+
const outerRightParent = fakeElement({ children: [rowB1, rowB2] })
27+
const nestedParent = fakeElement({
28+
parent: fakeElement({ closest: outerLeftParent }),
29+
children: [nestedRow],
30+
})
31+
32+
const root = fakeElement({
33+
children: [outerLeftParent, nestedParent, outerRightParent],
34+
})
35+
36+
expect(collectKatexEquationLines(root)).toEqual([
37+
[rowA1, rowB1],
38+
[rowA2, rowB2],
39+
])
40+
})
41+
})

packages/client/builtin/KaTexBlockWrapper.vue

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { computed, onMounted, onUnmounted, ref, watchEffect } from 'vue'
2626
import { CLASS_VCLICK_HIDDEN, CLASS_VCLICK_TARGET, CLICKS_MAX } from '../constants'
2727
import { useSlideContext } from '../context'
2828
import { makeId } from '../logic/utils'
29+
import { collectKatexEquationLines } from './katex-lines'
2930
3031
const props = defineProps({
3132
ranges: {
@@ -77,26 +78,10 @@ onMounted(() => {
7778
if (hide)
7879
rangeStr = props.ranges[index.value + 1] ?? finallyRange.value
7980
80-
// KaTeX equations have col-align-XXX as parent
81-
const equationParents = el.value.querySelectorAll('.mtable > [class*=col-align]')
82-
if (!equationParents)
83-
return
84-
85-
// For each row we extract the individual equation rows
86-
const equationRowsOfEachParent = Array.from(equationParents)
87-
.map(item => Array.from(item.querySelectorAll(':scope > .vlist-t > .vlist-r > .vlist > span > .mord')))
8881
// This list maps rows from different parents to line them up
89-
const lines: Element[][] = []
90-
for (const equationRowParent of equationRowsOfEachParent) {
91-
equationRowParent.forEach((equationRow, idx) => {
92-
if (!equationRow)
93-
return
94-
if (Array.isArray(lines[idx]))
95-
lines[idx].push(equationRow)
96-
else
97-
lines[idx] = [equationRow]
98-
})
99-
}
82+
const lines = collectKatexEquationLines(el.value)
83+
if (!lines.length)
84+
return
10085
10186
const startLine = props.startLine
10287
const highlights: number[] = parseRangeString(lines.length + startLine - 1, rangeStr)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const KATEX_EQUATION_PARENT_SELECTOR = '.mtable > [class*=col-align]'
2+
const KATEX_EQUATION_ROW_SELECTOR = ':scope > .vlist-t > .vlist-r > .vlist > span > .mord'
3+
4+
export function collectKatexEquationLines(el: Element): Element[][] {
5+
const equationParents = Array.from(el.querySelectorAll(KATEX_EQUATION_PARENT_SELECTOR))
6+
.filter(parent => !parent.parentElement?.closest(KATEX_EQUATION_PARENT_SELECTOR))
7+
8+
const lines: Element[][] = []
9+
for (const equationRowParent of equationParents) {
10+
const equationRows = Array.from(equationRowParent.querySelectorAll(KATEX_EQUATION_ROW_SELECTOR))
11+
equationRows.forEach((equationRow, idx) => {
12+
if (!equationRow)
13+
return
14+
if (Array.isArray(lines[idx]))
15+
lines[idx].push(equationRow)
16+
else
17+
lines[idx] = [equationRow]
18+
})
19+
}
20+
21+
return lines
22+
}

0 commit comments

Comments
 (0)