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