Skip to content

Commit

Permalink
Cleaning
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Yu committed Feb 16, 2024
1 parent dd74beb commit b4b4304
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 121 deletions.
2 changes: 1 addition & 1 deletion src/extras/math-preview-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ async function update(ev?: UpdateEvent) {
if (vscode.workspace.getConfiguration('latex-workshop').get('mathpreviewpanel.cursor.enabled', false)) {
await renderCursor(document, texMath)
}
const result = await lw.preview.math.generateSVG(texMath, cachedMacros).catch(() => undefined)
const result = await lw.preview.math.tex2svg(texMath, cachedMacros).catch(() => undefined)
if (!result) {
return
}
Expand Down
112 changes: 71 additions & 41 deletions src/preview/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,24 @@ import type { SupportedExtension } from 'mathjax-full'
import type { IMathJaxWorker } from './math/mathjax'
import { lw } from '../lw'
import type { ReferenceItem, TeXMathEnv } from '../types'
import * as utils from '../utils/svg'
import { getCurrentThemeLightness } from '../utils/theme'
import { stripComments } from '../utils/utils'
import { renderCursor as renderCursorWorker } from './math/mathpreviewlib/cursorrenderer'
import { type ITextDocumentLike, TextDocumentLike } from './math/mathpreviewlib/textdocumentlike'
import { type ITextDocumentLike } from './math/mathpreviewlib/textdocumentlike'
import { findMacros } from './math/mathpreviewlib/newcommandfinder'
import { TeXMathEnvFinder } from './math/mathpreviewlib/texmathenvfinder'
import { MathPreviewUtils } from './math/mathpreviewlib/mathpreviewutils'

const logger = lw.log('Preview', 'Math')

export const math = {
refreshMathColor,
onRef,
onTeX,
findRef,
findTeX,
findMath,
generateSVG,
ref2svg,
renderCursor,
typeset
tex2svg,
renderCursor
}

const pool: workerpool.WorkerPool = workerpool.pool(
Expand All @@ -51,13 +48,13 @@ async function onTeX(document: vscode.TextDocument, tex: TeXMathEnv, macros: str
const configuration = vscode.workspace.getConfiguration('latex-workshop')
const scale = configuration.get('hover.preview.scale') as number
let s = await renderCursor(document, tex)
s = MathPreviewUtils.mathjaxify(s, tex.envname)
const typesetArg = macros + MathPreviewUtils.stripTeX(s, macros)
s = mathjaxify(s, tex.envname)
const typesetArg = macros + stripTeX(s, macros)
const typesetOpts = { scale, color: foreColor }
try {
const xml = await typeset(typesetArg, typesetOpts)
const md = utils.svgToDataUrl(xml)
return new vscode.Hover(new vscode.MarkdownString(MathPreviewUtils.addDummyCodeBlock(`![equation](${md})`)), tex.range )
const md = svg2DataUrl(xml)
return new vscode.Hover(new vscode.MarkdownString(addDummyCodeBlock(`![equation](${md})`)), tex.range )
} catch(e) {
if (macros !== '') {
logger.log(`Failed rendering MathJax ${typesetArg} . Try removing macro definitions.`)
Expand Down Expand Up @@ -98,33 +95,39 @@ async function onRefMathJax(refData: ReferenceItem, ctoken?: vscode.Cancellation
const link = vscode.Uri.parse('command:latex-workshop.synctexto').with({ query: JSON.stringify([line, refData.file]) })
const mdLink = new vscode.MarkdownString(`[View on pdf](${link})`)
mdLink.isTrusted = true
return new vscode.Hover( [MathPreviewUtils.addDummyCodeBlock(`![equation](${md})`), mdLink], refData.math?.range )
return new vscode.Hover( [addDummyCodeBlock(`![equation](${md})`), mdLink], refData.math?.range )
}

async function ref2svg(refData: ReferenceItem, ctoken?: vscode.CancellationToken) {
if (refData.math === undefined) {
return ''
}
const texMath = refData.math
const configuration = vscode.workspace.getConfiguration('latex-workshop')
const scale = configuration.get('hover.preview.scale') as number

const macros = await findMacros(ctoken)

let newTeXString: string
let texStr: string | undefined = undefined
if (refData.prevIndex !== undefined && configuration.get('hover.ref.number.enabled') as boolean) {
const tag = refData.prevIndex.refNumber
const texString = replaceLabelWithTag(refData.math.texString, refData.label, tag)
newTeXString = MathPreviewUtils.mathjaxify(texString, refData.math.envname, {stripLabel: false})
} else {
newTeXString = MathPreviewUtils.mathjaxify(refData.math.texString, refData.math.envname)
const texString = replaceLabelWithTag(texMath.texString, refData.label, tag)
texStr = mathjaxify(texString, texMath.envname, {stripLabel: false})
}
const typesetArg = macros + MathPreviewUtils.stripTeX(newTeXString, macros)
const svg = await tex2svg(texMath, macros, texStr)
return svg.svgDataUrl
}

async function tex2svg(tex: TeXMathEnv, macros?: string, texStr?: string) {
macros = macros ?? await findMacros()
const configuration = vscode.workspace.getConfiguration('latex-workshop')
const scale = configuration.get('hover.preview.scale') as number
texStr = texStr ?? mathjaxify(tex.texString, tex.envname)
texStr = macros + stripTeX(texStr, macros)
try {
const xml = await lw.preview.math.typeset(typesetArg, { scale, color: foreColor })
const svg = utils.svgToDataUrl(xml)
return svg
const xml = await typeset(texStr, {scale, color: foreColor})
return { svgDataUrl: svg2DataUrl(xml), macros }
} catch(e) {
logger.logError(`Failed rendering MathJax ${typesetArg} .`, e)
logger.logError(`Failed rendering MathJax ${texStr} .`, e)
throw e
}
}
Expand Down Expand Up @@ -163,15 +166,6 @@ function refNumberMessage(refData: Pick<ReferenceItem, 'prevIndex'>): string | u
return
}

async function generateSVG(tex: TeXMathEnv, macros?: string) {
macros = macros ?? await findMacros()
const configuration = vscode.workspace.getConfiguration('latex-workshop')
const scale = configuration.get('hover.preview.scale') as number
const s = MathPreviewUtils.mathjaxify(tex.texString, tex.envname)
const xml = await typeset(macros + MathPreviewUtils.stripTeX(s, macros), {scale, color: foreColor})
return { svgDataUrl: utils.svgToDataUrl(xml), macros }
}

function refreshMathColor() {
foreColor = getCurrentThemeLightness() === 'light' ? '#000000' : '#ffffff'
}
Expand All @@ -188,15 +182,51 @@ function findTeX(document: ITextDocumentLike, position: vscode.Position): TeXMat
return TeXMathEnvFinder.findHoverOnTex(document, position)
}

function findRef(
refData: Pick<ReferenceItem, 'file' | 'position'>,
token: string
) {
const document = TextDocumentLike.load(refData.file)
const position = refData.position
return TeXMathEnvFinder.findHoverOnRef(document, position, refData, token)
}

function findMath(document: ITextDocumentLike, position: vscode.Position): TeXMathEnv | undefined {
return TeXMathEnvFinder.findMathEnvIncludingPosition(document, position)
}

function addDummyCodeBlock(md: string): string {
// We need a dummy code block in hover to make the width of hover larger.
const dummyCodeBlock = '```\n```'
return dummyCodeBlock + '\n' + md + '\n' + dummyCodeBlock
}

function stripTeX(tex: string, macros: string): string {
// First remove math env declaration
if (tex.startsWith('$$') && tex.endsWith('$$')) {
tex = tex.slice(2, tex.length - 2)
} else if (tex.startsWith('$') && tex.endsWith('$')) {
tex = tex.slice(1, tex.length - 1)
} else if (tex.startsWith('\\(') && tex.endsWith('\\)')) {
tex = tex.slice(2, tex.length - 2)
} else if (tex.startsWith('\\[') && tex.endsWith('\\]')) {
tex = tex.slice(2, tex.length - 2)
}
// Then remove the star variant of new macros
[...macros.matchAll(/\\newcommand\{(.*?)\}/g)].forEach(match => {
tex = tex.replaceAll(match[1] + '*', match[1])
})
return tex
}

function mathjaxify(tex: string, envname: string, opt = { stripLabel: true }): string {
// remove TeX comments
let s = stripComments(tex)
// remove \label{...}
if (opt.stripLabel) {
s = s.replace(/\\label\{.*?\}/g, '')
}
if (envname.match(/^(aligned|alignedat|array|Bmatrix|bmatrix|cases|CD|gathered|matrix|pmatrix|smallmatrix|split|subarray|Vmatrix|vmatrix)$/)) {
s = '\\begin{equation}' + s + '\\end{equation}'
}
return s
}

function svg2DataUrl(xml: string): string {
// We have to call encodeURIComponent and unescape because SVG can includes non-ASCII characters.
// We have to encode them before converting them to base64.
const svg64 = Buffer.from(unescape(encodeURIComponent(xml)), 'binary').toString('base64')
const b64Start = 'data:image/svg+xml;base64,'
return b64Start + svg64
}
40 changes: 0 additions & 40 deletions src/preview/math/mathpreviewlib/mathpreviewutils.ts

This file was deleted.

34 changes: 2 additions & 32 deletions src/preview/math/mathpreviewlib/texmathenvfinder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as vscode from 'vscode'
import type { ReferenceItem, TeXMathEnv } from '../../../types'
import type { TeXMathEnv } from '../../../types'
import * as utils from '../../../utils/utils'
import { type ITextDocumentLike, TextDocumentLike } from './textdocumentlike'
import { type ITextDocumentLike } from './textdocumentlike'

const ENV_NAMES = [
'align', 'align\\*', 'alignat', 'alignat\\*', 'aligned', 'alignedat', 'array', 'Bmatrix', 'bmatrix', 'cases', 'CD', 'eqnarray', 'eqnarray\\*', 'equation', 'equation\\*', 'flalign', 'flalign\\*', 'gather', 'gather\\*', 'gathered', 'matrix', 'multline', 'multline\\*', 'pmatrix', 'smallmatrix', 'split', 'subarray', 'Vmatrix', 'vmatrix'
Expand All @@ -27,36 +27,6 @@ export class TeXMathEnvFinder {
return TeXMathEnvFinder.findHoverOnInline(document, position)
}

static findHoverOnRef(
document: ITextDocumentLike,
position: vscode.Position,
refData: Pick<ReferenceItem, 'file' | 'position'>,
token: string,
): TeXMathEnv | undefined {
const limit = vscode.workspace.getConfiguration('latex-workshop').get('hover.preview.maxLines') as number
const docOfRef = TextDocumentLike.load(refData.file)
const envBeginPatMathMode = new RegExp(`\\\\begin\\{(${MATH_ENV_NAMES.join('|')})\\}`)
const l = docOfRef.lineAt(refData.position.line).text
const pat = new RegExp('\\\\label\\{' + utils.escapeRegExp(token) + '\\}')
const m = l.match(pat)
if (m && m.index !== undefined) {
const labelPos = new vscode.Position(refData.position.line, m.index)
const beginPos = TeXMathEnvFinder.findBeginPair(docOfRef, envBeginPatMathMode, labelPos, limit)
if (beginPos) {
const t = TeXMathEnvFinder.findHoverOnTex(docOfRef, beginPos)
if (t) {
const beginEndRange = t.range
const refRange = document.getWordRangeAtPosition(position, /\S+?\{.*?\}/)
if (refRange && beginEndRange.contains(labelPos)) {
t.range = refRange
return t
}
}
}
}
return
}

static findMathEnvIncludingPosition(document: ITextDocumentLike, position: vscode.Position): TeXMathEnv | undefined {
const limit = vscode.workspace.getConfiguration('latex-workshop').get('hover.preview.maxLines') as number
const envNamePatMathMode = new RegExp(`(${MATH_ENV_NAMES.join('|')})`)
Expand Down
7 changes: 0 additions & 7 deletions src/utils/svg.ts

This file was deleted.

0 comments on commit b4b4304

Please sign in to comment.