├── .gitignore ├── example.png ├── lib2.bib ├── canvasTemplate.html ├── LICENSE.md ├── highlightCode.py ├── README.md ├── addEquationNumbers.py ├── textToHtml.py ├── input.md └── input.tex /.gitignore: -------------------------------------------------------------------------------- 1 | output.html -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubengerritsen/LatexToCanvas/HEAD/example.png -------------------------------------------------------------------------------- /lib2.bib: -------------------------------------------------------------------------------- 1 | @article{Born1927, 2 | author = {Born, M and Oppenheimer, R}, 3 | journal = {Annalen der Physik}, 4 | title = {Zur Quantentheorie der Molekeln}, 5 | volume = {84}, 6 | year = {1927} 7 | } -------------------------------------------------------------------------------- /canvasTemplate.html: -------------------------------------------------------------------------------- 1 |
2 | $if(toc)$ 3 |
4 |

Contents

5 | 8 |
9 | $endif$ 10 | $body$ 11 |
12 | $for(include-after)$ 13 | $include-after$ 14 | $endfor$ 15 |
16 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ruben Gerritsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /highlightCode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Created on Wed Sep 2 13:22:12 2020 4 | 5 | @author: ruben 6 | """ 7 | 8 | from __future__ import print_function 9 | import sys 10 | import pandocfilters as pf 11 | 12 | from pygments import highlight 13 | from pygments.lexers import get_lexer_by_name 14 | from pygments.formatters import HtmlFormatter 15 | 16 | def eprint(*args, **kwargs): 17 | """ Equivalent to print(), but prints to stderr. 18 | 19 | Needed (for debuggin)since we can't print to stdout, since 20 | that disrupts the pipeline. 21 | """ 22 | print(*args, file=sys.stderr, **kwargs) 23 | 24 | def get_default_style(): 25 | """ CSS specification of the code block style. 26 | 27 | might interfere with the formatting done by Canvas, so 28 | keep it basic. 29 | """ 30 | return '' 31 | 32 | def highlightCode(code, language='python', style='default'): 33 | """ Highlights plain text string as code. 34 | 35 | @params: 36 | code: a string containing the basic code to format 37 | language: programming language to base highlighting on 38 | style: choose color scheme options: ['default', 'emacs', 'friendly', 39 | 'colorful', 'autumn', 'murphy', 'manni', 'monokai', 'perldoc', 40 | 'pastie', 'borland', 'trac', 'native', 'fruity', 'bw', 'vim', 41 | 'vs', 'tango', 'rrt', 'xcode', 'igor', 'paraiso-light', 42 | 'paraiso-dark', 'lovelace', 'algol', 'algol_nu', 'arduino', 43 | 'rainbow_dash', 'abap'] 44 | """ 45 | lexer = language 46 | style = style 47 | formatter = HtmlFormatter(style=style, 48 | linenos=False, 49 | noclasses=True, 50 | cssclass='', 51 | cssstyles= get_default_style(), 52 | nobackground=True 53 | ) 54 | html = highlight(code, get_lexer_by_name(lexer), formatter) 55 | return html 56 | 57 | 58 | def formatCode(key, value, format, meta): 59 | style = 'default' 60 | if key == 'CodeBlock': 61 | if value[0][1]: 62 | return pf.Plain([pf.RawInline("html", highlightCode(value[1],style=style, language=value[0][1][0]))]) 63 | else: 64 | return pf.Plain([pf.RawInline("html", highlightCode(value[1],style=style, language='text'))]) 65 | 66 | if __name__ == "__main__": 67 | pf.toJSONFilter(formatCode) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Latex and Markdown To Canvas LMS Pages 2 | This tool converts LaTeX (.tex) and Markdown (.md) files to plain HTML that can be used as a basis for pages in Canvas LMS. 3 | 4 | Some of the features 5 | 6 | * Syntax highlighting for code (without CSS) 7 | * Equation numbers and referencing (for TeX files) 8 | * Citations via the `\cite{}` command and a .bib file (for TeX files) 9 | * Automatic table of contents 10 | 11 | ### Markdown 12 | If you do not need equation support the tool can also be applied to markdown files. In this case the tool reduces to `pandoc` with an inplace syntax highlighter, so no additional CSS or HTML head is needed. 13 | 14 | # Usage 15 | The tool is made to be as easy as possible, to see what it can do run 16 | 17 | ```bash 18 | ./textToHtml.py input.tex 19 | ``` 20 | or on windows 21 | ```bash 22 | python3 textToHtml.py input.tex #it might be that python3 does not work use python instead 23 | ``` 24 | 25 | This will create a html page called `output.html`, the contents of this file can be copy pasted in the HTML editor of a Canvas page or viewed in a browser (NB in the last case not all features might work). The generated page will give a more detailed explanation of what the tool can do and how to customize the output. 26 | 27 | ### Markdown usage 28 | 29 | ```bash 30 | ./textToHtml.py input.md 31 | ``` 32 | 33 | ### Example output (page fragment) 34 | ![](example.png) 35 | 36 | # Dependencies and Install 37 | The tool is made in python and based around pandoc, hence a working python version is necessary. Pandoc can be installed via this [link](https://pandoc.org/installing.html), there is an installer, but also instructions for how to do it via the command line. 38 | 39 | The syntax highlighting and equation numbering depend on two other python packages `pandocfilters` and `pygments`. They can be installed with `pip3 install ` 40 | 41 | ### For Windows Users 42 | Start off by installing [pandoc](https://pandoc.org/installing.html). Just follow the installer instructions. 43 | 44 | Next open a powershell (windows button + `X`, followed by `I`), type `python3` and press enter. If python is installed it will open and you can exit again, type `exit()` followed by an enter. If python is not installed it will lead you to the microsoft store where you can get/download it, press the button and let windows do the rest. 45 | 46 | Now that we have python installed return to the powershell and type `pip3 install pandocfilters` press enter and repeat for `pip3 install pygments`. 47 | 48 | Next navigate (in powershell with `cd`) to the folder where the files of this repository are and type `python3 textToHtml.py input.tex` (if `python3` is not recognized try `python`) and press enter. An html file called `output.html` is now created, copy paste its contents in the HTML editor of a Canvas page and you should now see the example page. 49 | 50 | 51 | ## Files 52 | Every pandoc filter and template has its own file, these files should be accessible to the program while running. The easiest way to achieve this is by putting them in the working directory. The files needed are 53 | * `highlightCode.py` provides syntax highlighting 54 | * `addEquationNumbers.py` provides equation numbers 55 | * `canvasTemplate.html` provides a template for the page we generate. In the example template I have used it to set the width of the page to 900 pixels. 56 | -------------------------------------------------------------------------------- /addEquationNumbers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Created on Wed Sep 2 13:22:12 2020 4 | 5 | @author: ruben 6 | """ 7 | 8 | import sys 9 | import re 10 | import functools 11 | import json 12 | import io 13 | 14 | # pandoc imports 15 | import pandocfilters as pf 16 | from pandocfilters import elt as _elt 17 | 18 | # GLOBAL VARIABLES 19 | eqNumber = 0 20 | labelMap = dict() 21 | 22 | def eprint(*args, **kwargs): 23 | """ Equivalent to print(), but prints to stderr. 24 | 25 | Needed (for debuggin)since we can't print to stdout, since 26 | that disrupts the pipeline. 27 | """ 28 | print(*args, file=sys.stderr, **kwargs) 29 | 30 | def elt(eltType, numargs): # pylint: disable=invalid-name 31 | """Returns Element(*value) function to create pandoc AST elements. 32 | 33 | This should be used in place of pandocfilters.elt(). This version 34 | ensures that the content is stored in a list, not a tuple. 35 | """ 36 | def Element(*value): # pylint: disable=invalid-name 37 | """Creates an element.""" 38 | el = _elt(eltType, numargs)(*value) 39 | if isinstance(el['c'], tuple): 40 | el['c'] = list(el['c']) # The content should be a list, not tuple 41 | return el 42 | return Element 43 | 44 | def add_eq_number_and_id(fmt, value, num, labelName): 45 | num = str(num) 46 | outer = pf.RawInline('html', 47 | f'') 48 | inner = pf.RawInline('html', '') 49 | eqno = pf.Str('(%s)' % num) 50 | endtags = pf.RawInline('html', '') 51 | return [outer, elt('Math', 2)(*value), inner, eqno, endtags] 52 | 53 | 54 | def createLabelMapAndAddEqNum(key, value, format, meta): 55 | global eqNumber, labelMap 56 | if key == 'Math' and value[0]['t'] == 'DisplayMath': 57 | eqNumber = eqNumber + 1 58 | label = re.search(r'\\label\{(.*?)\}',value[1]) 59 | labelName = " " 60 | if label != None: 61 | labelName = label.group(1) 62 | labelMap[labelName] = eqNumber 63 | return add_eq_number_and_id(format, value, eqNumber, labelName) 64 | 65 | def applyLabelMapToText(key, value, format, meta): 66 | global labelMap 67 | if key == 'Link': 68 | if value[0][2] != []: 69 | if value[0][2][1][1] in labelMap: 70 | value[1][0]['c'] = '(%s)' % labelMap[value[0][2][1][1]] 71 | 72 | 73 | 74 | if __name__ == "__main__": 75 | """ Add equation numbers and process references to equations. 76 | 77 | The basic idea is very simple, we run through the document once, 78 | give every equation an equation number and if the equation has 79 | a label, we add the label and eq number to a dictionary called 80 | 'labelMap'. Then we do a second pass through the document and 81 | change all \ref{} to the correct equation number, 82 | based on the labelMap. 83 | """ 84 | STDIN = io.TextIOWrapper(sys.stdin.buffer, 'utf-8', 'strict') 85 | STDOUT = io.TextIOWrapper(sys.stdout.buffer, 'utf-8', 'strict') 86 | STDERR = io.TextIOWrapper(sys.stderr.buffer, 'utf-8', 'strict') 87 | 88 | fmt = "html" 89 | doc = json.loads(STDIN.read()) 90 | meta = doc['meta'] 91 | blocks = doc['blocks'] 92 | 93 | # first pass 94 | altered = functools.reduce(lambda x, action: pf.walk(x, action, fmt, meta), [createLabelMapAndAddEqNum, ], blocks) 95 | 96 | # second pass 97 | altered = functools.reduce(lambda x, action: pf.walk(x, action, fmt, meta), [applyLabelMapToText, ], altered) 98 | 99 | # update the document 100 | doc['blocks'] = altered 101 | 102 | # put the result to stdout 103 | json.dump(doc, STDOUT) 104 | STDOUT.flush() 105 | -------------------------------------------------------------------------------- /textToHtml.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import subprocess 5 | import shutil 6 | 7 | options = { 8 | ######## USER INPUT ######### 9 | "sectionNr": True, 10 | "TOC": True, 11 | "TOC_depth": 2, 12 | "pathToBib": "lib2.bib", 13 | "template": "canvasTemplate.html", 14 | "filters": ["highlightCode.py", 15 | "addEquationNumbers.py"] 16 | ############################# 17 | } 18 | 19 | 20 | def helpMessage(): 21 | return (""" 22 | OVERVIEW: 23 | This tool helps to convert LaTeX (.tex) of Markdown (.md) files to 24 | plain HTML. It supports syntax highlighting for code blocks (lstlisting), 25 | equation numbers and links to equations. It provides these 26 | functions in plain HTML, so no CSS or external sources are needed. 27 | The only thing it can't handle are images, it will process them, 28 | but they will probably not display in your HTML. They can however 29 | be added manually (not by this tool). 30 | 31 | DEPENDENCIES: 32 | This tool requires a working (and added to the path) installation 33 | of pandoc: 34 | 35 | https://pandoc.org/installing.html 36 | 37 | To use the filters for syntax highlighting and equation numbering 38 | we need to have the following python packages installed (the 39 | install command is a suggestion, conda, for example, comes with 40 | these packages pre installed, they may be old though!). 41 | 42 | * pandocfilters (INSTALL: pip3 install pandocfilters) 43 | * pygments (INSTALL: pip3 install pygments) 44 | 45 | USAGE: 46 | To use the tool simply run this file with as input parameter the 47 | .tex file and optionally the name of the output file. On Linux 48 | 49 | ./textToHtml.py .tex 50 | 51 | or 52 | 53 | ./textToHtml.py .tex .html 54 | 55 | NB: for all the features to work the following files should be 56 | accessible (preferably in the working directory) and .py files 57 | should be executable: 58 | 59 | * highlightCode.py 60 | * addEquationNumbers.py 61 | * htmlTemplate.html 62 | 63 | ADDITIONAL OPTIONS: 64 | To control the eventual look of the output HTML we can change 65 | all the default options in the textToHtml.py file, the options 66 | are at the top labelled 'USER INPUT'. The options to change 67 | 68 | * table of contents 69 | * section numbering 70 | * templates controls the layout of the HTML file 71 | * the bibliography source file 72 | * and which filters to use 73 | 74 | To change the colorscheme for syntax highlighting, change 75 | the style variable in the highlightCode.py filter source file. 76 | """) 77 | 78 | 79 | def runPandoc(inputFile, outputFile="output.html", markdown=False): 80 | global options 81 | 82 | #defaults 83 | args = ["pandoc", "--mathml", "--standalone", "--to=html"] 84 | 85 | # input file format 86 | if markdown: 87 | args.append("--from=markdown") 88 | else: 89 | args.append("--from=latex") 90 | 91 | 92 | # Processing options 93 | if options["sectionNr"]: 94 | args.append("--number-offset=0") 95 | if options["TOC"]: 96 | args.append("--toc") 97 | if "TOC_depth" in options: 98 | args.append(f"--toc-depth={options['TOC_depth']}") 99 | if "pathToBib" in options: 100 | args.append(f"--bibliography={options['pathToBib']}") 101 | if "template" in options: 102 | args.append(f"--template={options['template']}") 103 | for filter in options["filters"]: 104 | args.append(f"--filter={filter}") 105 | 106 | args.append(f"--output={outputFile}") 107 | args.append(inputFile) 108 | # run pandocs 109 | print(f"Processing: {inputFile}") 110 | subprocess.Popen(args) 111 | print(f"HTML is written to: {outputFile}") 112 | 113 | 114 | if __name__ == "__main__": 115 | if (shutil.which("pandoc") == None): 116 | print("No pandoc installation found.") 117 | exit() 118 | 119 | userOptions = sys.argv 120 | 121 | if len(userOptions) == 1: 122 | print("Please specify at least an input file (.tex or .md)") 123 | print("General usage: textToHtml.py .tex .html") 124 | print("For a help message use: textToHtml.py help") 125 | 126 | if len(userOptions) == 2: 127 | if userOptions[1][-4:] == ".tex": 128 | runPandoc(userOptions[1]) 129 | elif userOptions[1][-3:] == ".md": 130 | runPandoc(userOptions[1], markdown=True) 131 | elif userOptions[1].find("help") != -1: 132 | print(helpMessage()) 133 | else: 134 | print("Only .tex or .md files are supported.") 135 | 136 | if len(userOptions) == 3: 137 | if userOptions[1][-4:] == ".tex": 138 | runPandoc(userOptions[1], userOptions[2]) 139 | elif userOptions[1][-3:] == ".md": 140 | runPandoc(userOptions[1], userOptions[2], markdown=True) 141 | else: 142 | print("Only .tex or .md files are supported.") 143 | -------------------------------------------------------------------------------- /input.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown Reference 3 | date: "2020-07-23" 4 | tags: [markdown, math, floats] 5 | thumbnail: ./mdImage.png 6 | description: A markdown reference cheat. 7 | --- 8 | 9 | 10 | # A Markdown Reference 11 | 12 | This markdown file is an adapted version of the standard [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) often used as a reference, test and showcase. 13 | 14 | ## Headers 15 | 16 | ``` 17 | # Heading 1 18 | ## Heading 2 19 | ### Heading 3 20 | #### Heading 4 21 | ##### Heading 5 22 | ###### Heading 6 23 | 24 | Alternatively, for H1 and H2, an underline-ish style: 25 | 26 | Alt-H1 27 | ====== 28 | 29 | Alt-H2 30 | ------ 31 | ``` 32 | 33 | # Heading 1 34 | 35 | ## Heading 2 36 | 37 | ### Heading 3 38 | 39 | #### Heading 4 40 | 41 | ##### Heading 5 42 | 43 | ###### Heading 6 44 | 45 | Alternatively, for H1 and H2, an underline-ish style: 46 | 47 | # Alt-H1 48 | 49 | ## Alt-H2 50 | 51 | ## Emphasis 52 | 53 | ``` 54 | Emphasis, aka italics, with *asterisks* or _underscores_. 55 | 56 | Strong emphasis, aka bold, with **asterisks** or __underscores__. 57 | 58 | Combined emphasis with **asterisks and _underscores_**. 59 | 60 | Strikethrough uses two tildes. ~~Scratch this.~~ 61 | ``` 62 | 63 | Emphasis, aka italics, with _asterisks_ or _underscores_. 64 | 65 | Strong emphasis, aka bold, with **asterisks** or **underscores**. 66 | 67 | Combined emphasis with **asterisks and _underscores_**. 68 | 69 | Strikethrough uses two tildes. ~~Scratch this.~~ 70 | 71 | ## Lists 72 | 73 | ``` 74 | 1. First ordered list item 75 | 2. Another item 76 | * Unordered sub-list. 77 | 1. Actual numbers don't matter, just that it's a number 78 | 1. Ordered sub-list 79 | 4. And another item. 80 | 81 | Some text that should be aligned with the above item. 82 | 83 | * Unordered list can use asterisks 84 | - Or minuses 85 | + Or pluses 86 | ``` 87 | 88 | 1. First ordered list item 89 | 90 | 2. Another item 91 | 92 | - Unordered sub-list. 93 | 94 | 3. Actual numbers don't matter, just that it's a number 95 | 96 | 1. Ordered sub-list 97 | 98 | 4. And another item. 99 | 100 | Some text that should be aligned with the above item. 101 | 102 | - Unordered list can use asterisks 103 | 104 | - Or minuses 105 | 106 | - Or pluses 107 | 108 | ## Links 109 | 110 | There are two ways to create links. 111 | 112 | ``` 113 | [I'm an inline-style link](https://www.google.com) 114 | 115 | Or leave it empty and use the [link text itself] 116 | ``` 117 | 118 | [I'm an inline-style link](https://www.google.com) 119 | 120 | Or leave it empty and use the [link text itself] 121 | 122 | Fully qualified URLs will automatically be turned into links. 123 | http://www.example.com 124 | 125 | ## Blockquotes 126 | 127 | ``` 128 | > Blockquotes are very handy in email to emulate reply text. 129 | >> Blockquote in blockquote 130 | >> This line is part of the same quote. 131 | 132 | Quote break. 133 | 134 | > This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote. 135 | ``` 136 | 137 | > Blockquotes are very handy in email to emulate reply text. 138 | >> Blockquote in blockquote 139 | >> This line is part of the same quote. 140 | 141 | Quote break. 142 | 143 | > This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can _put_ **Markdown** into a blockquote. 144 | 145 | ## Horizontal Rule 146 | 147 | ``` 148 | Three or more... 149 | 150 | --- 151 | 152 | Hyphens 153 | 154 | *** 155 | 156 | Asterisks 157 | 158 | ___ 159 | 160 | Underscores 161 | ``` 162 | 163 | Three or more... 164 | 165 | ------ 166 | 167 | Hyphens 168 | 169 | ------ 170 | 171 | Asterisks 172 | 173 | ------ 174 | 175 | Underscores 176 | 177 | ## Line Breaks 178 | 179 | My basic recommendation for learning how line breaks work is to experiment and discover -- hit <Enter> once (i.e., insert one newline), then hit it twice (i.e., insert two newlines), see what happens. You'll soon learn to get what you want. "Markdown Toggle" is your friend. 180 | 181 | Here are some things to try out: 182 | 183 | ``` 184 | Here's a line for us to start with. 185 | 186 | This line is separated from the one above by two newlines, so it will be a *separate paragraph*. 187 | 188 | This line is also a separate paragraph, but... 189 | This line is only separated by a single newline, so it's a separate line in the *same paragraph*. 190 | ``` 191 | 192 | Here's a line for us to start with. 193 | 194 | This line is separated from the one above by two newlines, so it will be a _separate paragraph_. 195 | 196 | This line is also begins a separate paragraph, but... 197 | This line is only separated by a single newline, so it's a separate line in the _same paragraph_. 198 | 199 | (Technical note: _Markdown Here_ uses GFM line breaks, so there's no need to use MD's two-space line breaks.) 200 | 201 | ------ 202 | 203 | ## Code Highlighting 204 | 205 | ```javascript 206 | // In your gatsby-config.js 207 | // Let's make this line very long so that our container has to scroll its overflow… 208 | plugins: [ 209 | { 210 | resolve: `gatsby-transformer-remark`, 211 | options: { 212 | plugins: [ 213 | { 214 | resolve: `gatsby-remark-images`, 215 | options: { 216 | maxWidth: 756, 217 | }, 218 | }, 219 | { 220 | resolve: `gatsby-remark-responsive-iframe`, 221 | options: { 222 | wrapperStyle: `margin-bottom: 1.0725rem`, 223 | }, 224 | }, 225 | `gatsby-remark-copy-linked-files`, 226 | `gatsby-remark-smartypants`, 227 | `gatsby-remark-prismjs`, 228 | ] 229 | } 230 | } 231 | ] 232 | ``` 233 | 234 | Let's do something crazy and add a list with another code example: 235 | 236 | - **A list item** 237 | 238 | …and a paragraph! In my younger and more vulnerable years my father gave me 239 | some advice that I’ve been turning over in my mind ever since. 240 | 241 | 1. A nested numbered list 242 | 2. “Whenever you feel like criticizing any one,” he told me, “just remember 243 | that all the people in this world haven’t had the advantages that you’ve 244 | had.” 245 | 246 | - Roger that, now back to topic: _Highlighted code blocks work here, too:_ 247 | 248 | ```css 249 | .clearfix:after { 250 | visibility: hidden; 251 | display: block; 252 | font-size: 0; 253 | content: " "; 254 | clear: both; 255 | height: 0; 256 | } 257 | .clearfix { display: inline-table; } 258 | /* Hides from IE-mac \*/ 259 | * html .clearfix { height: 1%; } 260 | .clearfix { display: block; } 261 | /* End hide from IE-mac */ 262 | ``` 263 | 264 | Wow, "IE-mac"? 265 | [Yeah, that was a thing](https://en.wikipedia.org/wiki/Internet_Explorer_for_Mac) 266 | back in the day … a good one at the time, too: 267 | 268 | > Initial versions were developed from the same code base as Internet Explorer 269 | > for Windows. Later versions diverged, particularly with the release of 270 | > version 5 which included the cutting edge, 271 | > [fault-tolerant](https://en.wikipedia.org/wiki/Fault-tolerant) and highly 272 | > standards-compliant 273 | > [Tasman]() > 274 | > [layout engine](https://en.wikipedia.org/wiki/Layout_engine). 275 | 276 | Source: https://en.wikipedia.org/wiki/Internet_Explorer_for_Mac 277 | 278 | - **The last list item** –- no more list items after this one, pinky swear! 279 | 280 | --- 281 | -------------------------------------------------------------------------------- /input.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt, a4paper]{article} 2 | \usepackage[utf8]{inputenc} 3 | % Page setup (margin's) 4 | \usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} 5 | \pagestyle{plain} 6 | % Maths 7 | \usepackage{amsmath} 8 | \usepackage{amssymb} 9 | \usepackage{amsthm} 10 | % Floats and figures 11 | \usepackage{float} 12 | \usepackage{graphicx} 13 | \usepackage{caption} 14 | \usepackage{listings} 15 | \usepackage{xcolor} 16 | \usepackage{hyperref} 17 | 18 | \definecolor{commentsColor}{rgb}{0.497495, 0.497587, 0.497464} 19 | \definecolor{keywordsColor}{rgb}{0.000000, 0.000000, 0.635294} 20 | \definecolor{stringColor}{rgb}{0.558215, 0.000000, 0.135316} 21 | 22 | \title{some title} 23 | 24 | 25 | \begin{document} 26 | 27 | \section{Introduction} 28 | This is a small demo document that shows how LaTeX (or markdown) can be used as a basis for Canvas pages (and plain HTML pages in general). Using \lstinline|pandoc| with the appropriate filters, we can get much of the LaTeX functionality to plain HTML. This HTML can then be copy pasted in the Canvas HTML editor to form the basis of a page. Some of the main features are 29 | \begin{itemize} 30 | \item Equation numbering and referencing, 31 | \item Citations via .bib files and the \lstinline|\cite{}| command 32 | \item Highlighted code (without the need of additional CSS) 33 | \item and more \ldots 34 | \end{itemize} 35 | 36 | \noindent 37 | There are two parts to this document. Firstly we show what the tool can do and secondly we show how to setup and use the tool. 38 | 39 | \section{What It Can Do} 40 | 41 | \subsection{Math and Equations} 42 | In Canvas MathJax is not supported but MathML is. We can use it for inline math equations $a^2+b^2 = c^2$ and also for more complex equations in an equation environment. 43 | \begin{equation} 44 | v_{ij}= 45 | \begin{cases} 46 | v_0 \exp(-2\alpha R_{ij} - \frac{E_j - E_i}{k_B T}) & E_j-E_i > 0\\ 47 | v_0 \exp(-2\alpha R_{ij}) & E_j-E_i \leq 0 48 | \end{cases}, \label{millerAbrahams} 49 | \end{equation} 50 | The nice thing is that we can reference equations as well, e.g. equation \ref{millerAbrahams}, it is even a link to the equation (click this one for example \ref{anotherLabel}). Now we add a few more equations just to show off the automatic equation numbering. 51 | \begin{align} 52 | \frac{dp_{i,e}}{dt} = \sum_{j\neq i} \left[ -p_{i,e} v_{ij,e} (1-p_{j,e}) + p_{j,e} v_{ji,e} (1-p_{i,e}) \right] - \frac{p_{i,e}p_{i,h}}{\tau} + c_i\frac{(1-p_{i,e})(1-p_{i,h})}{\tau}, \label{eq:electronME} \\ 53 | \frac{dp_{i,h}}{dt} = \sum_{j\neq i} \left[ -p_{i,h} v_{ij,h} (1-p_{j,h}) + p_{j,h} v_{ji,h} (1-p_{i,h}) \right] - \frac{p_{i,e}p_{i,h}}{\tau} + c_i\frac{(1-p_{i,e})(1-p_{i,h})}{\tau}. 54 | \end{align} 55 | Think of some original text here. 56 | \begin{equation} 57 | c_i = \frac{p_{i,e}p_{j,h}}{(1-p_{i,e})(1-p_{i,h})} = \exp\left(\frac{E_{i,h} - E_{i,e}}{k_B T}\right). \label{anotherLabel} 58 | \end{equation} 59 | 60 | 61 | \subsection{Code blocks} 62 | While talking about programming and code it is often useful to show the code. If we for example want to talk about the function \lstinline{twoBodyForce(xyzs,bonds,Kb,r0)} we can do so. If we want to show larger pieces of code, we can add it as a listing. There is (for as far as I know) no syntax highlighting in Canvas, which is annoying. Luckily using an extra filter we can generate highlighted code for almost all languages in plain HTML (no CSS needed) from a \lstinline{lstlisting} environment (TeX) or \lstinline{``` code block ```} (markdown). 63 | 64 | % Listings should not be indented, gives strange indent behaviour in HTML 65 | \begin{lstlisting}[language=python] 66 | def twoBodyForce(xyzs,bonds,Kb,r0): 67 | """ Calculates 'two body'-force for every bond in 'bonds'. """ 68 | # Calculate difference vector and distances 69 | global dimMAX 70 | dr = xyzs[bonds[:,1]] - xyzs[bonds[:,0]] 71 | dr = dr - np.floor(dr/dimMAX + 0.5)*dimMAX #correction for PBC 72 | distAt = np.linalg.norm(dr,axis = 1) 73 | # Calculate Potential Energy 74 | pEnergy = sum(0.5*Kb*(distAt -r0)**2) 75 | # Calculate forces 76 | forces = (Kb*(distAt-r0)/distAt)[:,np.newaxis]*dr 77 | # Assign forces to right atom 78 | tForce = np.zeros((len(xyzs),3)) 79 | np.add.at(tForce,bonds[:,0],forces) #NB. this is elementwise addiditon UNBUFFERED 80 | np.add.at(tForce,bonds[:,1],-forces) #NB. this is elementwise addiditon UNBUFFERED 81 | return(tForce,pEnergy) 82 | \end{lstlisting} 83 | 84 | \subsection{Lists} 85 | An example of an enumeration. 86 | \begin{enumerate} 87 | \item List item 1 88 | \item List item 2 89 | \item And more list items \ldots 90 | \end{enumerate} 91 | 92 | \subsection{Tables} 93 | An example table can be found in Table \ref{summary}. It is not perfect but very readable. 94 | \begin{table}[H] 95 | \centering 96 | \begin{tabular}{c|c|c|c } 97 | \hline \hline 98 | Name & Description & Default Value & Unit \\ \hline 99 | $N_s$ & Number of sites & 512 & - \\ 100 | $T$ & Number of simulated hops & $2\cdot 10^6$ & - \\ 101 | $v_{ij}$ & Hopping rate & - & - \\ 102 | $v_0$ & Attempt to escape frequency & 1 & - \\ 103 | $\alpha$ & Inverse localization length & 0.15 & nm$^{-1}$ \\ 104 | $k_B T$ & Thermal energy in system & 0.026 & eV \\ 105 | $r_{c}$ & Cut-off distance for determining neighbours & 20 & nm \\ 106 | $p_{ij}$ & Transition probability from state $i\rightarrow j$. & - & -\\ 107 | $S(i)$ & Set of neighbours of site $i$ & - &- \\ 108 | $E_i$ & Energy of site/state $i$ & - & eV \\ 109 | $R_{ij}$ & Distance between site $i$ and $j$ & - & nm \\ 110 | $\mu$ & Mean of the Gaussian DOS & 1.5 & eV \\ 111 | $\sigma$ & Standard deviation of the Gaussian DOS & $2k_B T$ & eV \\ 112 | $e$ & Electron charge & 1 & ${e}$ \\ 113 | $F$ & Electric field strength & - & \\ 114 | \hline 115 | \end{tabular} 116 | \caption{Summary of some simulation parameters.}\label{summary} 117 | \end{table} 118 | 119 | \subsection{Images (what it cannot do)} 120 | Adding images is a bit more complex because we need to have the correct relative path to the image. Which we cannot know up front, since Canvas generates some number as the identifier for the image. Hence we cannot do anything for images, but do not despair, this is the only moment where it is a pleasure to use the \lstinline{rich content editor} of Canvas to drag and drop images in place (after you have copy pasted the HTML). 121 | 122 | \subsection{Citations} 123 | Adding citations can be done in the normal LaTeX way, for example here is a reference to the Born Oppenheimer paper about their famous approximation \cite{Born1927}. If we provide the right bibliography file the references are automatically added to the end of the HTML file. 124 | 125 | \subsection{Links To Websites} 126 | Using the command \lstinline|\href{https://pandoc.org/installing.html}{Pandoc}| we can link to the install page of \href{https://pandoc.org/installing.html}{Pandoc}. 127 | 128 | \subsection{References to Equations and Tables} 129 | References to the tables work (e.g. Table \ref{summary}) and equation references work as well (e.g. Equation \ref{millerAbrahams}). 130 | 131 | \section{Setup and Usage} 132 | All the source files for the tool can be downloaded from \href{https://github.com/rubengerritsen/LatexToCanvas}{GitHub}, including the file to generate this page. 133 | 134 | \subsection{Dependencies} 135 | The tool is made in python and based around pandoc, hence a working python version is necessary. Pandoc can be installed via this \href{https://pandoc.org/installing.html}{link}, there is an installer, but also instructions for how to do it via the command line. 136 | 137 | The syntax highlighting and equation numbering depend on two other python packages \lstinline{pandocfilters} and \lstinline{pygments}. They can be installed with \lstinline|pip3 install | 138 | 139 | \subsection{Files} 140 | Every pandoc filter and template has its own file, these files should be accessible to the program while running. The easiest way to achieve this is by putting them in the working directory. The files needed are 141 | 142 | \begin{itemize} 143 | \item \lstinline|highlightCode.py| provides syntax highlighting 144 | \item \lstinline|addEquationNumbers.py| provides equation numbers 145 | \item \lstinline|canvasTemplate.html| provides a template for the page we generate. In the example template I have used it to set the width of the page to 900 pixels. 146 | \end{itemize} 147 | 148 | \subsection{Usage} 149 | To use the tool, simply run the \lstinline|textToHtml.py| file with as input parameter the .tex file and optionally the name of the output file. On Linux 150 | \begin{lstlisting}[language=bash] 151 | ./textToHtml.py .tex 152 | \end{lstlisting} 153 | or 154 | \begin{lstlisting}[language=bash] 155 | ./textToHtml.py .tex .html 156 | \end{lstlisting} 157 | If no output file is provided it will put the output in \lstinline|output.html|. 158 | 159 | \subsection{Control Over The Output (Options)} 160 | There are multiple ways to control the generated output. For starters we can change options in the \lstinline|textToHtml.py| file (they are at the top of the file). Available options are 161 | \begin{itemize} 162 | \item \lstinline|sectionNr| if True sections will be numbered, 163 | \item \lstinline|TOC| if True a table of contents will be added, 164 | \item \lstinline|TOC_depth| sets toc depth, 165 | \item \lstinline|pathToBib| sets the path to a bibliography (.bib) file, 166 | \item \lstinline|template| sets which template to use and 167 | \item \lstinline|filters| additional filters can be added here. 168 | \end{itemize} 169 | 170 | The colorscheme used for syntax highlighting can be set in the \lstinline|highlighCode.py| file. Simply change the style variable to whatever style you want. As long as the style is recognized by pygments it will work. 171 | 172 | Finally the page layout can be set by changing the template file. 173 | 174 | \section{How It Works} 175 | This tool is nothing but a python wrapper around \href{https://pandoc.org}{pandoc} with some additional filters for equation numbering and syntax highlighting. The actual command that is used looks something like this 176 | \begin{lstlisting}[language=bash] 177 | pandoc --toc --toc-depth=2 --filter highlightCode.py --filter addEquationNumbers.py --mathml --standalone --bibliography= --template canvasTemplate.html -f latex -t html input.tex -o output.html 178 | \end{lstlisting} 179 | All source files are well documented, have a look at those if you want a deeper understanding of what is going on. 180 | 181 | 182 | 183 | \section{Bibliography} 184 | \bibliographystyle{ieeetr} 185 | \bibliography{/home/ruben/Documents/lib2.bib} 186 | 187 | \end{document} --------------------------------------------------------------------------------