Pluto: how to number equations in LaTeX mode

Maybe I am missing some similar post already raised before. I have done my best, looking for such a topic, but I haven’t found one. How can I number an equation (written in LaTeX mode) in Pluto? The quality of the LaTeX output is fantastic, but if we use Pluto for teaching, the numbering of equations becomes a vital issue. I can skip the crossref thing (at least, I still can do it manually), but the numbering of equations is essential.

4 Likes

There is an open issue regarding this. Maybe there you can find a workaround.

1 Like

@fenanor There is another issue (488) where @zmoon shows very clearly what should be done. It does not look that complicated to introduce this functionality into Pluto.

Good to know. Maybe this configuration can be injected into the page using a script tag in one on the pluto cells.

I think this is similar to what the TableOfContents() object from PlutoUI does.

http://docs.mathjax.org/en/latest/web/configuration.html#configuring-mathjax-after-it-is-loaded

May something like this works, but my js is knowledge is a bit outdated.

MathJax.config.tex.tags = "ams"
MathJax.startup.getComponents()

I have tried your suggestions but get the error: UndefVarError: MathJax not defined.

Anyway, thanks for your help.

@VivMendes
I have been playing a bit with the @tex macro that @fonsp posted a while ago on zulip and was able to recreate automatic equation numbering as well as referencing in other cells of the notebook.

You can find the example notebook here:

Ad here is a gif of the basic functionality:
82074c75-ceef-4e94-ac72-7a42e4653976

If you don’t need the equation references as hyperlinks you can skip using the big cell with a lot of javascript code and just use the two function definitions eqref and texeq.

Unfortunately you still need to double escape every backslash for putting the text on the equation environment but that can probably be fixed when PR #1032 is merged into Pluto by using a string literal macro

20 Likes

@disberd, wow, this is awesome. I was only looking for automatic numbers in LaTeX equations but get hyperlinks and even LaTeX output produced by Julia code!!! This is amazing.

I spotted a minor issue that may result from my clumsy use of your code. I inserted an equation that is not numbered. However, in the hyperlinks, that equation is also considered in the numbering process. Please find the example below.

For me, your solution is more than enough. Thank you very much.

1 Like

Thanks for spotting this.
It was actually a bug in the code.

try this updated cell code for the counter javascript code

@htl """
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css" integrity="sha384-Um5gpz1odJg5Z4HAmzPtgZKdTBHZdw8S29IecapCSB31ligYPhHQZMIlWLYQGVoc" crossorigin="anonymous">

<style>
a.eq_href {
	text-decoration: none;
}
</style>

		<script src="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.js" integrity="sha384-YNHdsYkH6gMx9y3mRkmcJ2mFUjTd0qNQQvY9VYZgQd7DcN7env35GzlmFaZ23JGp" crossorigin="anonymous"></script>

<script id="katex-eqnum-script">

const a_vec = [] // This will hold the list of a tags with custom click, used for cleaning listeners up upon invalidation

const eqrefClick = (e) => {
	e.preventDefault() // This prevent normal scrolling to link
	const a = e.target
	const eq_id = a.getAttribute('eq_id')
	window.location.hash = 'eqref-' + eq_id // This is to be able to use the back function to resume previous view, 'eqref-' is added in front to avoid the viewport actually going to the equation without having control of the scroll
	const eq = document.getElementById(eq_id)
	eq.scrollIntoView({
		behavior: 'smooth',
		block: 'center',
	})
}

const checkCounter = (item, i) => {
	return item.classList.contains('enclosing')	?
	i											:
	i + 1
}

const updateCallback = () => {
a_vec.splice(0,a_vec.length) // Reset the array
const eqs = document.querySelectorAll('span.enclosing, span.eqn-num')
let i = 0;
eqs.forEach(item => {
	i = checkCounter(item,i)
	console.log('item',i,'=',item)
	if (item.classList.contains('enclosing')) {
		const id = item.id
		const a_vals = document.querySelectorAll(`[eq_id=\${id}]`)
		a_vals !== null && a_vals.forEach(a => {
			a_vec.push(a) // Add this to the vector
			a.innerText = `(\${i+1})`
			a.addEventListener('click',eqrefClick)
		})
	}
})
}

const notebook = document.querySelector("pluto-notebook")

// We have a mutationobserver for each cell:
const observers = {
	current: [],
}

const createCellObservers = () => {
	observers.current.forEach((o) => o.disconnect())
	observers.current = Array.from(notebook.querySelectorAll("pluto-cell")).map(el => {
		const o = new MutationObserver(updateCallback)
		o.observe(el, {attributeFilter: ["class"]})
		return o
	})
}
createCellObservers()

// And one for the notebook's child list, which updates our cell observers:
const notebookObserver = new MutationObserver(() => {
	updateCallback()
	createCellObservers()
})
notebookObserver.observe(notebook, {childList: true})

invalidation.then(() => {
	notebookObserver.disconnect()
	observers.current.forEach((o) => o.disconnect())
	a_vec.forEach(a => a.removeEventListener('click',eqrefClick))
})
</script>
"""

I have also updated the reference notebook on github

3 Likes

Linking this very useful discussion to the corresponding Pluto issue

Thanks @disberd for the workaround, would love to see this more tightly integrated into Pluto.

2 Likes

@disberd, thanks for taking the time to solve that minor issue (if one did not like it, one could number all equations). Nevertheless, it is better as it stands now.

As far as my understanding goes, many people are looking for this functionality in Pluto. Before submitting this initial post, I searched for similar concerns and found many people looking for this type of functionality. In your piece, this is not just a workaround: that trick of using Julia code to export its outcome to a formatted LaTeX equation is just magic. I am not a professional programmer (I am just using Julia for professional reasons) and never suspected that this trick could be achieved as quickly as you have done it. I hope @fons takes a serious look at your contributions — this one and the other that makes the integration of PlotlyJS with Pluto flawless here.

3 Likes

@VivMendes, thanks for the kind words.

I am just so amazed by Pluto capabilities that I started using it extensively for my own work/research and it is incredible what the combination of Julia on the backend and JS/HTML on the front end can let you achieve.
This gave me a very big incentive to study some of the front-end stuff to get what I want out of Pluto notebooks.
I’ll keep trying improving and finding new functionalities within Pluto for my own use and to help other, but a very big thank you here is due to the core developers of Pluto for creating this amazing package where basically imagination is the limit :smiley:

4 Likes

This is really wonderful. Thank you so much!!
Is it possible to refer to different equations in one array?

2 Likes

Thanks for spotting this issue!

I had a quick look and it seems a bit tricky to be able to support correct numbering in this case but I’ll try when I have some spare time and let you know

1 Like

@frankhuettner
I should have updated the javascript code of initialize_eqref to also correctly handle the align environments now.
Now that macro analysis is a thing I should also look into making a string literal macro of this but I have other priorities at the moment :smiley:

You can find the update notebook for testing at the same url on my repo posted above

5 Likes

Thank you!

Hi everyone,

I am returning to some Pluto notebooks that have been idle for 6/7 months. The workaround developed by @disberd to auto-number LaTeX equations worked remarkably well for earlier versions of Pluto. It still does, but now Pluto spits out some replica of the LateX code, which is related to something to the terminal stream. Please see below a simple example. This looks like a result of a minor conflict between @disberd’s workaround and Pluto v.0.19.9. Any idea whether this inconvenient message can be eliminated? Thanks.

2 Likes

Amazing!

@VivMendes, are you using a copy-paste version of the code I had on PlutoUtils.jl?

The main fix is to remove printing from my code (back then Pluto was not capturing the stdout).
A more bruteforce solution is also disabling stdout capture all together in the Pluto session by starting it with the flag
Pluto.run(;capture_stdout = false).

2 Likes

@disberd, thanks. Yes, I am using a copy/past version of your code. I wrote these Pluto notebooks last summer when you made available your solution to auto-numbering LaTeX equations inside Pluto. At that time, I was experiencing a conflict between your PlutoUtils version and some other version.

Apparently, I still suffer from some form of conflict: I have your PlutoUtils package installed, but Pluto does not recognize it.


Hi @VivMendes, the problem with the package not being found is that you are adding it to your generic julia environment, while Pluto creates a separate environment per notebook with the integrated PkgManager so it is not finding your package.

Again, the main culprit here is me again. I should just publish my package in the General Registry so it’s easier for people to use it (you may notice that I already changed the name to PlutoUtilities to avoid a conflict with another existing package with the name PlutoUtils in the JuliaPluto organization).
I wanted to do some refactoring but I will publish the package in the next days so these issues should be solved.

Meanwhile, you can easily remove the log message without disabling stdout capturing by just going on the code of the texeq function in my code and remove/comment out the line println(code_escaped), as you can see on the image below:

I also updated the code on the repo to stop printing to stdout

2 Likes