Algotype.js - Typesetting algorithms in HTML files

Table of contents


Algotype.js?

This vanilla JavaScript library allows users to typeset pseudocode with custom XML tags and MathJax in HTML documents. The motivation was that people (for the most part) don't need to take representation of pseudocode into account, but rather concentrate on algorithm logic.


Including Algotype.js

In order to load the Algotype.js library, all you need is:

<link rel="stylesheet" type="text/css" href="algotype_my_config.css">
<script src="algotype.js"></script>
        

in the <head> of the HTML file. The file algotype_my_config.css is supposed to contain style overrides for algorithm elements (see Highlighting code and comments).


Dependencies

Algotype.js automatically loads MathJax library for writing TeX.


Documentation

Algotype.js tags


alg-algorithm

Summary

The tag alg-algorithm defines an entire algorithm. Naturally, it may have all inner elements except alg-algorithm.

Synopsis

<alg-algorithm name="Algorithm-Name$(x, A, R, Z)$"
               comment="Algorithm header comment">
...
</alg-algorithm>
        
The above will be rendered as follows

headerthe name of the algorithm and the argument listrequired
commentthe algorithm commentoptional
algorithm-upper-header-classthe CSS class for styling the upper header baroptional
algorithm-lower-header-classthe CSS class for styling the lower header baroptional
algorithm-footer-classthe CSS class for styling the footer baroptional

Notes


alg-break

Summary

The tag alg-break typesets a break statement. This element may not have inner elements.

Synopsis

<alg-break id="break-id" 
           comment="Break comment" 
           comment-id="break-comment-id">Label<alg-break>
        
The above will be rendered as follows at line 1:

Label

idthe break statement IDoptional
commentthe break statement commentoptional
comment-idthe break statement comment IDoptional

Notes


alg-continue

Summary

The tag alg-continue typesets a continue statement. This element may not have inner elements.

Synopsis

<alg-continue id="continue-id" 
              comment="Continue comment" 
              comment-id="continue-comment-id">Label</alg-continue>
        
The above will be rendered as follows at line 1:

Label

idthe continue statement IDoptional
commentthe continue statement commentoptional
comment-idthe continue statement comment IDoptional

Notes


alg-else

Summary

The alg-else tag typesets the else branches. This element may have other inner elements.

Synopsis

<alg-else id="else-id" 
          comment="Else comment" 
          comment-id="else-comment-id">
...
</alg-else>        
        
The above will be rendered as follows at line 1:

...

id the else statement ID optional
comment the else statement comment optional
comment-id the else statement comment ID optional

alg-else-if

Summary

The alg-else-if tag typesets the else-if branches. This element may have other inner elements.

Synopsis

<alg-else-if condition="$n \leq 1$" 
             id="else-if-id" 
             comment="Else if comment" 
             comment-id="else-if-comment-id">
...
</alg-else-if>
        
The above will be rendered as follows at line 1:

...

condition the else if condition required
id the else if statement ID optional
comment the else if statement comment optional
comment-id the else if statement comment ID optional

alg-error

Summary

The alg-error tag typesets the errors and exception raises. This element may not have inner elements.

Synopsis

<alg-error id="error-id"
           comment="Error comment"
           comment-id="error-comment-id">Error text here</alg-error>
        

Error text here

id the error statement ID optional
comment the error statement comment optional
comment-id the error statement comment ID optional

alg-for

Summary

The alg-for tag typesets the for loops. This element may have other inner elements.

Synopsis

<alg-for init="$i = 1$" 
         to="$n$" 
         step="$2$" 
         label="loop_label" 
         id="for-id" 
         comment="For comment" 
         comment-id="for-comment-id">
...
</alg-for>
        
The above will be rendered as follows at line 1:

...

init the loop counter initialization required
to the loop counter upper bound required
step the step value optional
label the loop label optional
id the for statement ID optional
comment the for statement comment optional
comment-id the for statement comment ID optional

alg-foreach

Summary

The alg-foreach tag typesets the for each loops. This element may have other inner elements.

Synopsis

<alg-foreach condition="$x \in Q$" 
             label="loop_label" 
             id="foreach-id" 
             comment="For each comment" 
             comment-id="foreach-comment-id>
...
</alg-foreach>
        
The above will be rendered as follows at line 1:

...

condition the loop condition required
label the loop label optional
id the for each statement ID optional
comment the for each statement comment optional
comment-id the for each statement comment ID optional

alg-forever

Summary

The alg-forever tag typesets the forever loops that iterate unconditionally. This element may have other inner elements.

Synopsis

<alg-forever label="loop_label" 
             id="forever-id" 
             comment="Forever comment" 
             comment-id="forever-comment-id">
...
</alg-forever>
        
The above will be rendered as follows at line 1:

...

label the loop label optional
id the forever statement ID optional
comment the forever statement comment optional
comment-id the forever statement comment ID optional

alg-for-downto

Summary

The alg-for-downto tag typesets the for loops that countdown the counter. This element may have other inner elements.

Synopsis

<alg-for-downto init="$i = n$" 
                to="$1$" 
                step="$2$"
                label="loop_label" 
                id="for-downto-id" 
                comment="For down to comment" 
                comment-id="for-downto-comment-id">
...
</alg-for-downto>
        
The above will be rendered as follows at line 1:

...

init the loop counter initialization required
to the loop counter lower bound required
step the step value optional
label the loop label optional
id the for downto statement ID optional
comment the for downto statement comment optional
comment-id the for downto statement comment ID optional

alg-if

Summary

The alg-if tag typesets the if branches. This element may have other inner elements.

Synopsis

<alg-if condition="$n > 1$" 
        id="if-id" 
        comment="If comment" 
        comment-id="if-comment-id">
...
</alg-if>
        
The above will be rendered as follows at line 1:

...

condition the if condition required
id the if statement ID optional
comment the if statement comment optional
comment-id the if statement comment ID optional

alg-repeat-until

Summary

The alg-repeat-until tag typesets the loops whose condition is evaluated after each iteration. This element may have other inner elements.

Synopsis

<alg-repeat-until condition="$n > 0$" 
                  label="loop_label" 
                  id="repeat-until-id" 
                  comment="Repeat until comment" 
                  comment-id="repeat-until-comment-id">
...
</alg-repeat-until>
        
The above will be rendered as follows:

...

condition the loop condition required
label the loop label optional
id the repeat until statement ID optional
comment the repeat until statement comment optional
comment-id the repeat until statement comment ID optional

alg-output

Summary

The alg-output tag typesets the output statements. This element may not have inner elements.

Synopsis

<alg-output id="output-id" 
            comment="Output comment" 
            comment-id="output-comment-id">$1 \; + $ Aux-Procedure$(x, y, Q)$</alg-output>
        
The above will be rendered as follows:

$1 \; +$ Aux-Procedure$(x, y, Q)$

id the output statement ID optional
comment the output statement comment optional
comment-id the output statement comment ID optional

Notes

In the alg-output element, all text not delimeted by $ TeX delimeters is considered to be a function call and is thus typeset using small-caps font just like the algorithm name.

alg-print

Summary

The alg-print tag typesets the print statements. This element may not have inner elements.

Synopsis

<alg-print id="print-id" 
           comment="Print comment" 
           comment-id="print-comment-id">$1 \; + $ Aux-Procedure$(x, y, Q)$</alg-print>
        

The above will be rendered as follows: $1 \; +$ Aux-Procedure$(x, y, Q)$

id the print statement ID optional
comment the print statement comment optional
comment-id the print statement comment ID optional

Notes

In the alg-print element, all text not delimeted by $ TeX delimeters is considered to be a function call and is thus typeset using small-caps font just like the algorithm name.

alg-return

Summary

The alg-return tag typesets the return statements. This element may not have inner elements.

Synopsis

<alg-return id="return-id" 
            comment="Return comment" 
            comment-id="return-comment-id">$1 \; + $ Aux-Procedure$(x, y, Q)$</alg-return>
        
The above will be rendered as follows at line 1:

$1 \; +$ Aux-Procedure$(x, y, Q)$

id the return statement ID optional
comment the return statement comment optional
comment-id the return statement comment ID optional

Notes

In the alg-return element, all text not delimeted by $ TeX delimeters is considered to be a function call and is thus typeset using small-caps font just like the algorithm name.

alg-step

Summary

The alg-step tag typesets a single step/non-block statement. This element may not have inner elements.

Synopsis

<alg-step id="step-id" 
          comment="Step comment" 
          comment-id="step-comment-id">$x \leftarrow 1 \; + $ Aux-Procedure$(x, y, Q)$</alg-step>
        
The above will be rendered as follows at line 1:

$x \leftarrow 1 \; +$ Aux-Procedure$(x, y, Q)$

id the step statement ID optional
comment the step statement comment optional
comment-id the step statement comment ID optional

Notes

In the alg-step element, all text not delimeted by $ TeX delimeters is considered to be a function call and is thus typeset using small-caps font just like the algorithm name.

alg-while

Summary

The alg-while tag typesets the while loops.

Synopsis

<alg-while condition="$x > $0" 
           label="loop_label" 
           id="while-id" 
           comment="While comment" 
           comment-id="while-comment-id">
...
</alg-while>
        
The above will be rendered as follows at line 1:

...

condition the iteration condition required
label the loop label optional
id the while statement ID optional
comment the while statement comment optional
comment-id the while statement comment ID optional

alg-yield

Summary

The alg-yield tag typesets the yield statements. This element may not have inner elements.

Synopsis

<alg-yield id="yield-id" 
           comment="Yield comment" 
           comment-id="yield-comment-id">$1 \; + $ Aux-Procedure$(x, y, Q)$</alg-yield>
        
The above will be rendered as follows:

$1 \; +$ Aux-Procedure$(x, y, Q)$

id the yield statement ID optional
comment the yield statement comment optional
comment-id the yield statement comment ID optional

Notes

In the alg-yield element, all text not delimeted by $ TeX delimeters is considered to be a function call and is thus typeset using small-caps font just like the algorithm name.

Example

$X \leftarrow \varnothing$ outer $X \leftarrow X \cup \{ q \}$ $x \leftarrow$ Aux-Method$(q, r)$ $x \; + $ Prune$(q, r)$

The source for the above pseudocode is
<alg-algorithm header="Compute-Something-Interesting$(Q, R)$" 
                  comment="Interesting comment"  
                  algorithm-upper-header-class="upper_header_bar"
                  algorithm-lower-header-class="lower_header_bar"
                  algorithm-footer-class="footer_bar">
    <alg-step>$X \leftarrow \varnothing$</alg-step>
    <alg-foreach condition="$q \in Q$" label="outer">
        <alg-foreach condition="$r \in R$">
            <alg-if condition="$q = r$">
                <alg-continue>outer</alg-continue>
            </alg-if>
            <alg-else-if condition="$q < r$">
                <alg-step comment="Important step">$X \leftarrow X \cup \{ q \}$</alg-step>
            </alg-else-if>
            <alg-else>
                <alg-step>$x \leftarrow$ Aux-Method$(q, r)$</alg-step>
                <alg-return>$x \; + $ Prune$(q, r)$</alg-return>
            </alg-else>
        </alg-foreach>
    </alg-foreach>
</alg-algorithm>
        

Above, the header and footer styles are:

.upper_header_bar {
    border-top: 3px solid #ffaa33 !important;
    width: 474px;
}

.lower_header_bar {
    border-bottom: 2px solid black !important; 
    width: 474px;
}

.footer_bar {
    background-color: #ffaa33;
    width: 474px; 
    height: 3px;
}
        


Miscellany


Highlighting code and comments

The primary function of statement and comment IDs is to have a mechanism for changing the way they are rendered by default. Given CSS rules

#step_id1 {
    color: black;
}

#comment_id1 {
    color: black;
}

#step_id2 {
    color: brown;
}

#comment_id2 {
    color: black;
}

#step_id3 {
    color: black;
}

#comment_id3 {
    color: blue;
}

#step_id4 {
    color: brown;
}

#comment_id4 {
    color: blue;
}
        
and the algorithm
<alg-algorithm header="Dummy-Algorithm$()$">
    <alg-step id="step_id1" comment="Comment" comment-id="comment_id1">$x \leftarrow y + z$</alg-step>
    <alg-step id="step_id2" comment="Comment" comment-id="comment_id2">$x \leftarrow y + z$</alg-step>
    <alg-step id="step_id3" comment="Comment" comment-id="comment_id3">$x \leftarrow y + z$</alg-step>
    <alg-step id="step_id4" comment="Comment" comment-id="comment_id4">$x \leftarrow y + z$</alg-step>
</alg-algorithm>
        
we get the output

$x \leftarrow y + z$ $x \leftarrow y + z$ $x \leftarrow y + z$ $x \leftarrow y + z$

In case you need to color highlight only a part of a single statement, you can write, for example,

<alg-algorithm header="<span style='color:pink;'>Colorful</span>-Algorithm$(\color{red}x, \color{black}y)$" comment="<span style='color: brown;'>Color</span>ful comment">
    <alg-if condition="$\color{blue} x + y \color{black} > \color{red} 2 \; \And $ <span style='color:#789'>Call-Func</span>$(x, y)$">
        <alg-yield id="yield_id">$c \; \times $<span style='color:brown;'>Get-Factor</span>$\color{yellow}{(x, y)} + $ <span style='color:red;'>Fix-Constant</span>$()$</alg-yield>
        <alg-return>1 + <span style='color:red;'>Aux-Call</span>$\color{green}{(y, x + y)}$</alg-return>
    </alg-if>
</alg-algorithm>
            

which will give you

$c \; \times $Get-Factor$\color{yellow}{(x, y)} + $ Fix-Constant$()$ 1 + Aux-Call$\color{green}{(y, x + y)}$

If need be, you can define your custom colors for the TeX output. Just write

<span style="display:none;">$\definecolor{funky}{RGB}{255, 200, 0}$</span>
        

$\definecolor{funky}{RGB}{255, 200, 0}$

... and then, for example, ...

<alg-algorithm n="Pretty-Algorithm" parameters="">
    <alg-return>$1 + \color{funky} x + y \log x \color{black} \; + $ Helper-Func$(x, \color{funky} y \color{black})$</alg-return>
</alg-algorithm>
        

which will give you

$1 + \color{funky} x + y \log x \color{black} \; + $ Helper-Func$(x, \color{funky} y \color{black})$


Future improvements

  1. Fix the condition handling of if and else if such that it allows both TeX and function calls. (Jan 15, 2017) [Done at Jan 16, 2017 14:20]
  2. Make the source file algotype.js self sufficient: the library does not rely on external CSS file except custom overrides. (Jan 15, 2017) [Done at Jan 15, 2017 17:18]
  3. After moving the CSS rules to algotype.js (issue 2) the loop labels are not rendered correctly. (Jan 15, 2017) [Done at Jan 16, 2017 12:19]
  4. Add keywords print, output and yield. (Jan 16, 2017) [Done at Jan 16, 2017 13:35]
  5. Add then to if and else if. (Jan 16, 2017) [Done at Jan 16, 2017 13:36]
  6. Surround the algorithm headers with bottom and top horizontal lines. (Jan 16, 2017) [Done at Jan 16, 2017 19:25]
  7. Improve the algorithm header. (Jan 17, 2017) [Done at Jan 17, 2017 09:45]
  8. Make the code less DRY. (Jan 17, 2017) [Done at Jan 17, 2017 19:34]
  9. Devise a way for specifying the length of the horizontal algorithm header lines. (Jan 22, 2017) [Done at Jan 25, 2017 17:36]
  10. Devise a way for coloring the algorithm header. (Jan 23, 2017) [Done at Feb 2, 2017 11:09]
  11. Add the error keyword. (Jan 23, 2017) [Done at Jan 25, 2017 17:04]
  12. Devise a way for coloring the algorithm header bars. (Jan 25, 2017) [Done at Jul 24, 2017 10:14]
  13. Add the bottom footer bar. (Jul 23, 2017) [Done at Jul 24, 2017 10:14]
  14. Make the header and footer bars as long as the longest line in the pseudocode. (Jul 23, 2017) [Canceled at Jul 24, 2017 10:16]
  15. Allow the user to customize the header and footer bars. (Jul 24, 2017) [Done at Jul 24, 2017 10:16]
  16. Remove the trailing colons from the loops. (Jul 26, 2017) [Done at Jul 26, 2017 22:29]
  17. Fix away an empty line at the end of each algorithm when viewed in smartphones. (Feb 10, 2020)

Jul 26, 2017 22:29 by Rodion Efremov