Previously I wrote about how the code highlighter works for the website, and it has mostly remained identical to this.
I read an article recently (that I unfortunately lost) about how one website can run JS as if it were a Jupypter Notebook, which I thought is cool - but not very future proof. The whole idea of future-proof content is that even if the language were to die, methods change, the ideas and algorithms can still be used.
I decided to extend the pandoc highlight filter to allow for running Python (the easiest language to support), such that I now have the ability to write the code throughout a page and build a narrative around it.
Instead of using the following to write Python code:
0001 ```python 0002 print("hello") 0003 ```
I can instead use:
0004 ```python-exec 0005 print("hello") 0006 ```
In practice, it looks like this:
0007 print("hello")
hello
As you can now see, the result of writing that execution now appears below the code it ran.
It is quite limited, admittedly, but we can do some cool things with it. For example, we can declare a variable:
0008 a = 3 # first num 0009 b = 2 # second num
Then do something with it later:
0010 print("a = " + str(a)) 0011 print("b = " + str(b)) 0012 c = a * b 0013 print("a x b = " + str(c))
a = 3 b = 2 a x b = 6
This also applied to things such as functions:
0014 def factorial(n) : 0015 if n > 1 : 0016 return n * factorial(n - 1) 0017 return n
And again, using them later:
0018 print("8! = " + str(factorial(8))) 0019 print("16! = " + str(factorial(16))) 0020 print("32! = " + str(factorial(32))) 0021 print("64! = " + str(factorial(64))) 0022 print("128! = " + str(factorial(128)))
8! = 40320 16! = 20922789888000 32! = 263130836933693530167218012160000000 64! = 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000 128! = 385620482362580421735677065923463640617493109590223590278828403276373402575165543560686168588507361534030051833058916347592172932262498857766114955245039357760034644709279247692495585280000000000000000000000000000000
By default, each block runs in an exec()
call with its own globals dictionary. It is essentially able to do anything else, so cannot be considered safe for user input.
There is on the other hand a timeout of 10 seconds for each block using Unix signals - but this can be overridden using a try
/except
block to prevent termination. Ideally the code is small and well considered, if serious computation is needed, this should not be performed during the website build process, but instead offline elsewhere.
Code written in the python-exec
block should be carefully considered, as it could do literally anything the normal user can do.
I still need to tidy up the CSS so that it is more obvious what is output and what is not, but I will tackle this some other time 1.
As I hinted at previously, I would like to explore how different algorithms and code works and document this for others (and myself 2).