mirror of
https://github.com/James-Yu/LaTeX-Workshop.git
synced 2024-10-05 07:37:24 +03:00
use workerpool for MathPreview. Related to #1788
This commit is contained in:
parent
8a9da384bd
commit
f39770bc0a
29
src/providers/preview/mathjaxpool.ts
Normal file
29
src/providers/preview/mathjaxpool.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import {Extension} from '../../main'
|
||||
import * as path from 'path'
|
||||
import * as workerpool from 'workerpool'
|
||||
|
||||
type TypesetArg = {
|
||||
width?: number,
|
||||
equationNumbers?: string,
|
||||
math: string,
|
||||
format: string,
|
||||
svgNode: boolean,
|
||||
state?: any
|
||||
}
|
||||
|
||||
export class MathJaxPool {
|
||||
extension: Extension
|
||||
pool: workerpool.WorkerPool
|
||||
constructor(extension: Extension) {
|
||||
this.extension = extension
|
||||
this.pool = workerpool.pool(
|
||||
path.join(__dirname, 'mathjaxpool_worker.js'),
|
||||
{ minWorkers: 1, maxWorkers: 1, workerType: 'process' }
|
||||
)
|
||||
}
|
||||
|
||||
async typeset(arg: TypesetArg, opts: { scale: number, color: string }): Promise<string> {
|
||||
return await this.pool.exec('typeset', [arg, opts]).timeout(3000)
|
||||
}
|
||||
|
||||
}
|
50
src/providers/preview/mathjaxpool_worker.ts
Normal file
50
src/providers/preview/mathjaxpool_worker.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import * as workerpool from 'workerpool'
|
||||
import * as mj from 'mathjax-node'
|
||||
|
||||
mj.config({
|
||||
MathJax: {
|
||||
jax: ['input/TeX', 'output/SVG'],
|
||||
extensions: ['tex2jax.js', 'MathZoom.js'],
|
||||
showMathMenu: false,
|
||||
showProcessingMessages: false,
|
||||
messageStyle: 'none',
|
||||
SVG: {
|
||||
useGlobalCache: false
|
||||
},
|
||||
TeX: {
|
||||
extensions: ['AMSmath.js', 'AMSsymbols.js', 'autoload-all.js', 'color.js', 'noUndefined.js']
|
||||
}
|
||||
}
|
||||
})
|
||||
mj.start()
|
||||
|
||||
function scaleSVG(data: any, scale: number) {
|
||||
const svgelm = data.svgNode
|
||||
// w0[2] and h0[2] are units, i.e., pt, ex, em, ...
|
||||
const w0 = svgelm.getAttribute('width').match(/([.\d]+)(\w*)/)
|
||||
const h0 = svgelm.getAttribute('height').match(/([.\d]+)(\w*)/)
|
||||
const w = scale * Number(w0[1])
|
||||
const h = scale * Number(h0[1])
|
||||
svgelm.setAttribute('width', w + w0[2])
|
||||
svgelm.setAttribute('height', h + h0[2])
|
||||
}
|
||||
|
||||
function colorSVG(svg: string, color: string): string {
|
||||
const ret = svg.replace('</title>', `</title><style> * { color: ${color} }</style>`)
|
||||
return ret
|
||||
}
|
||||
|
||||
export async function typeset(arg: any, opts: { scale: number, color: string }) {
|
||||
try {
|
||||
const data = await mj.typeset(arg)
|
||||
scaleSVG(data, opts.scale)
|
||||
const xml = colorSVG(data.svgNode.outerHTML, opts.color)
|
||||
return xml
|
||||
} catch(e) {
|
||||
return e.stack
|
||||
}
|
||||
}
|
||||
|
||||
workerpool.worker({
|
||||
typeset
|
||||
})
|
@ -2,6 +2,8 @@ import * as vscode from 'vscode'
|
||||
import * as fs from 'fs'
|
||||
import {latexParser} from 'latex-utensils'
|
||||
import * as path from 'path'
|
||||
|
||||
import {MathJaxPool} from './mathjaxpool'
|
||||
import * as utils from '../../utils/utils'
|
||||
import {TextDocumentLike} from '../../components/textdocumentlike'
|
||||
import {Extension} from '../../main'
|
||||
@ -12,30 +14,12 @@ type TexMathEnv = { texString: string, range: vscode.Range, envname: string }
|
||||
|
||||
export class MathPreview {
|
||||
extension: Extension
|
||||
color: any
|
||||
mj: any
|
||||
color: string = '#000000'
|
||||
mj: MathJaxPool
|
||||
|
||||
constructor(extension: Extension) {
|
||||
this.extension = extension
|
||||
import('mathjax-node').then(mj => {
|
||||
mj.config({
|
||||
MathJax: {
|
||||
jax: ['input/TeX', 'output/SVG'],
|
||||
extensions: ['tex2jax.js', 'MathZoom.js'],
|
||||
showMathMenu: false,
|
||||
showProcessingMessages: false,
|
||||
messageStyle: 'none',
|
||||
SVG: {
|
||||
useGlobalCache: false
|
||||
},
|
||||
TeX: {
|
||||
extensions: ['AMSmath.js', 'AMSsymbols.js', 'autoload-all.js', 'color.js', 'noUndefined.js']
|
||||
}
|
||||
}
|
||||
})
|
||||
mj.start()
|
||||
this.mj = mj
|
||||
})
|
||||
this.mj = new MathJaxPool(extension)
|
||||
}
|
||||
|
||||
private async loadNewCommandFromConfigFile(newCommandFile: string) {
|
||||
@ -125,13 +109,13 @@ export class MathPreview {
|
||||
const scale = configuration.get('hover.preview.scale') as number
|
||||
let s = this.renderCursor(document, tex.range)
|
||||
s = this.mathjaxify(s, tex.envname)
|
||||
const data = await this.mj.typeset({
|
||||
const typesetArg = {
|
||||
math: newCommand + this.stripTeX(s),
|
||||
format: 'TeX',
|
||||
svgNode: true,
|
||||
})
|
||||
this.scaleSVG(data, scale)
|
||||
const xml = this.colorSVG(data.svgNode.outerHTML)
|
||||
}
|
||||
const typesetOpts = { scale, color: this.color }
|
||||
const xml = await this.mj.typeset(typesetArg, typesetOpts)
|
||||
const md = utils.svgToDataUrl(xml)
|
||||
return new vscode.Hover(new vscode.MarkdownString(this.addDummyCodeBlock(`![equation](${md})`)), tex.range )
|
||||
}
|
||||
@ -171,16 +155,16 @@ export class MathPreview {
|
||||
const newTex = this.replaceLabelWithTag(tex.texString, refData.label, tag)
|
||||
const s = this.mathjaxify(newTex, tex.envname, {stripLabel: false})
|
||||
const obj = { labels : {}, IDs: {}, startNumber: 0 }
|
||||
const data = await this.mj.typeset({
|
||||
const typesetArg = {
|
||||
width: 50,
|
||||
equationNumbers: 'AMS',
|
||||
math: newCommand + this.stripTeX(s),
|
||||
format: 'TeX',
|
||||
svgNode: true,
|
||||
state: {AMS: obj}
|
||||
})
|
||||
this.scaleSVG(data, scale)
|
||||
const xml = this.colorSVG(data.svgNode.outerHTML)
|
||||
}
|
||||
const typesetOpts = { scale, color: this.color }
|
||||
const xml = await this.mj.typeset(typesetArg, typesetOpts)
|
||||
const md = utils.svgToDataUrl(xml)
|
||||
const line = refData.position.line
|
||||
const link = vscode.Uri.parse('command:latex-workshop.synctexto').with({ query: JSON.stringify([line, refData.file]) })
|
||||
@ -224,22 +208,6 @@ export class MathPreview {
|
||||
return newTex
|
||||
}
|
||||
|
||||
private scaleSVG(data: any, scale: number) {
|
||||
const svgelm = data.svgNode
|
||||
// w0[2] and h0[2] are units, i.e., pt, ex, em, ...
|
||||
const w0 = svgelm.getAttribute('width').match(/([.\d]+)(\w*)/)
|
||||
const h0 = svgelm.getAttribute('height').match(/([.\d]+)(\w*)/)
|
||||
const w = scale * Number(w0[1])
|
||||
const h = scale * Number(h0[1])
|
||||
svgelm.setAttribute('width', w + w0[2])
|
||||
svgelm.setAttribute('height', h + h0[2])
|
||||
}
|
||||
|
||||
private colorSVG(svg: string): string {
|
||||
const ret = svg.replace('</title>', `</title><style> * { color: ${this.color} }</style>`)
|
||||
return ret
|
||||
}
|
||||
|
||||
private stripTeX(tex: string): string {
|
||||
if (tex.startsWith('$$') && tex.endsWith('$$')) {
|
||||
tex = tex.slice(2, tex.length - 2)
|
||||
|
1
types/mathjax-node/index.d.ts
vendored
1
types/mathjax-node/index.d.ts
vendored
@ -1,2 +1,3 @@
|
||||
export const config: any
|
||||
export function start(): any
|
||||
export function typeset(arg: any): Promise<any>
|
||||
|
Loading…
Reference in New Issue
Block a user