Numbering formulas

Hi I am new to Julia and want to
write latex code like here

md"""	Here's some inline maths: $\sqrt[n]{1 + x + x^2 + \ldots}$.

	Here's an equation:

	$\frac{n!}{k!(n - k)!} = \binom{n}{k}$

	This is the binomial coefficient.
	"""	

I was wondering in the following posts if the numbering would work for me:
https://discourse.julialang.org/t/pluto-how-to-number-equations-in-latex-mode/59900

I have problems by using

texeq("a+b=c") 

like in the posts. I get the

UndefVarError: texeq not defined

I install following packages

begin
    import Pkg
    # activate a temporary environment
    Pkg.activate(mktempdir())
    Pkg.add([
		Pkg.PackageSpec(name="PlutoUI"),
		Pkg.PackageSpec(name="HypertextLiteral"),
		Pkg.PackageSpec(name="Documenter"),
		Pkg.PackageSpec(url="https://github.com/fonsp/PlutoUtils.jl"),
		Pkg.PackageSpec(url="https://github.com/mossr/TeX.jl"),
    ])
end

and using

using Plots, PlutoUI, LinearAlgebra, PlutoUI, Markdown, InteractiveUtils, Documenter, HypertextLiteral, TeX

I want to use texeq and it does not work for numbering formulas

Hi,

Maybe, you have some conflict between PlutoUtils and Pluto, or some other package. The workaround developed by @disberd works immaculately for me. Try inserting these three lines of code into your Pluto notebook:

s(x) = HypertextLiteral.JavaScript(x)
"""
`texeq(code::String)`
Take an input string and renders it inside an equation environemnt (numbered) using KaTeX
Equations can be given labels by adding `"\\\\label{name}"` inside the `code` string and subsequently referenced in other cells using `eqref("name")`
# Note
Unfortunately backward slashes have to be doubled when creating the TeX code to be put inside the equation
When Pluto will support interpretation of string literal macros, this could be made into a macro
"""
function texeq(code,env="equation")
	code_escaped = code 			|>
	x -> replace(x,"\\" => "\\\\")	|>
	x -> replace(x,"\n" => " ")
	println(code_escaped)
	@htl """
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css" integrity="sha384-Um5gpz1odJg5Z4HAmzPtgZKdTBHZdw8S29IecapCSB31ligYPhHQZMIlWLYQGVoc" crossorigin="anonymous">
	<script src="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.js" integrity="sha384-YNHdsYkH6gMx9y3mRkmcJ2mFUjTd0qNQQvY9VYZgQd7DcN7env35GzlmFaZ23JGp" crossorigin="anonymous"></script>
	
	<script>
	katex.render('\\\\begin{$(js(env))} $(js(code_escaped)) \\\\end{$(js(env))}',currentScript.parentElement,{
					displayMode: true,
					trust: context => [
						'\\\\htmlId', 
						'\\\\href'
					].includes(context.command),
					macros: {
					  "\\\\label": "\\\\htmlId{#1}{}"
					},
				})
	</script>
	"""
end

"""
`eqref(label::String)`
Function that create an hyperlink pointing to a previously defined labelled equation using `texeq()`
"""
eqref(label) = @htl """
<a eq_id="$label" id="eqref_$label" href="#$label" class="eq_href">(?)</a>
"""

It should work. I am on a Windows 10 machine, using Julia 1.7.0 and Pluto 0.17.3.

I didn’t realize PlutoUtils was already taken as a name when i created it and didn’t end up changing the name.

texeq is not inside https://github.com/fonsp/PlutoUtils.jl but inside https://github.com/disberd/PlutoUtils.jl

You can also simply copy the relebant bits from the notebook and use it directly in your notebook as @VivMendes suggested.

@ga72kud, sorry, but in the copy+past exercise, I forgot to include a fourth block with code. As @disberd mentions, you can use his notebook that deals with the texeq function (the notebook has been recently updated). Or, you can open an entirely new notebook and insert the three code blocks I mentioned above, plus the fourth one below (all of them written by @disberd). The only package required for the notebook to run is HypertextLiteral.jl. Many thanks to disberd for this indispensable functionality inside Pluto notebooks, available nowhere else.

It works in a brand new notebook, Windows 10, Julia 1.7.0, Pluto 0.17.3.

The fourth code block that should be inserted into notebook is:

@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>
"""

1 Like

When trying to use texeq() (after copypasting the above lines) I get an error:

UndefVarError: js not defined

texeq(::String, ::String)@Other: 14
top-level scope@Local: 1[inlined]

So, which package exports js()?

@KajWiik , sorry, there was a typo in the first line of code: there was a “j” missing.

It should be:

js(x) = HypertextLiteral.JavaScript(x)

NOT as:

s(x) = HypertextLiteral.JavaScript(x)

1 Like

:grinning: Of course! I wondered where s() was used but was too lazy to look more carefully. Works perfectly, thanks!

Thank you !!!