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

11 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.

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

2 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.

2 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:

2 Likes

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

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

@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

3 Likes

Thank you!