├── LICENSE ├── README.md ├── _config.yml ├── img ├── es6_listing_example.png └── js_listing_example.png ├── js_listing.pdf └── js_listing.tex /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Gary Hammock 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LaTeX Listings — JavaScript & ES6 2 | 3 | The LaTeX [listings](https://ctan.org/pkg/listings?lang=en) package does not include (by default) a language specification for JavaScript/ECMAScript. However, the package provides the capability to create custom languages and styles based on built-in methods. These methods were used to create listings languages for JavaScript and ES6 (ECMAScript 2015). 4 | 5 | # Basic JavaScript 6 | 7 | First, the JavaScript version 1.1 definition is built in a way to allow for modifications to be built upon the basic language. Reference the [JavaScript v1.1 specification](http://hepunx.rl.ac.uk/~adye/jsspec11/titlepg2.htm). 8 | 9 | ## The code 10 | ```latex 11 | \lstdefinelanguage{JavaScript}{ 12 | morekeywords=[1]{break, continue, delete, else, for, function, if, in, 13 | new, return, this, typeof, var, void, while, with}, 14 | % Literals, primitive types, and reference types. 15 | morekeywords=[2]{false, null, true, boolean, number, undefined, 16 | Array, Boolean, Date, Math, Number, String, Object}, 17 | % Built-ins. 18 | morekeywords=[3]{eval, parseInt, parseFloat, escape, unescape}, 19 | sensitive, 20 | morecomment=[s]{/*}{*/}, 21 | morecomment=[l]//, 22 | morecomment=[s]{/**}{*/}, % JavaDoc style comments 23 | morestring=[b]', 24 | morestring=[b]" 25 | }[keywords, comments, strings] 26 | ``` 27 | 28 | ## Example 29 | 30 | ### Markup 31 | 32 | ```tex 33 | \begin{lstlisting}[style=JavaScript, caption={JavaScript Listing}] 34 | (function () { 35 | var user = getCookie("username"); 36 | document.getElementById("#date-field").innerHTML = new Date(); 37 | document.getElementById("#greetings").innerHTML = 38 | "

Hello, " + user.name + ".

"; 39 | })() 40 | 41 | function getCookie(cname) { 42 | var name = cname + "="; 43 | var decodedCookie = decodeURIComponent(document.cookie); 44 | var ca = decodedCookie.split(';'); 45 | for(var i = 0; i < ca.length; ++i) { 46 | var c = ca[i]; 47 | while (c.charAt(0) == ' ') { 48 | c = c.substring(1); 49 | } 50 | if (c.indexOf(name) == 0) { 51 | return c.substring(name.length, c.length); 52 | } 53 | } 54 | return ""; 55 | } 56 | \end{lstlisting} 57 | ``` 58 | 59 | ### Resulting Typeset 60 | ![Javascript Listing Example](img/js_listing_example.png) 61 | 62 | # ECMAScript 2015 (ES6) 63 | 64 | ES6 adds additional keywords and interpolated string capability. So these need to be reflected in the language defintion for `listings`. The `ECMAScript2015` dialect of the `JavaScript` language uses the base language and adds the additional keywords and string interpolation. 65 | 66 | There is an alias to map the language `ES6` to the `ECMAScript2015` dialect such that `language=ES6` is the same as `language=[ECMAScript2015]JavaScript`. 67 | 68 | ```tex 69 | \lstalias[]{ES6}[ECMAScript2015]{JavaScript} 70 | ``` 71 | 72 | ## The code 73 | ```latex 74 | \lstdefinelanguage[ECMAScript2015]{JavaScript}[]{JavaScript}{ 75 | morekeywords=[1]{await, async, case, catch, class, const, default, do, 76 | enum, export, extends, finally, from, implements, import, instanceof, 77 | let, static, super, switch, throw, try}, 78 | morestring=[b]` % Interpolation strings. 79 | } 80 | ``` 81 | 82 | ## Example 83 | 84 | ### Markup 85 | ```tex 86 | \begin{lstlisting}[style=ES6, caption={ES6 (ECMAScript-2015) Listing}] 87 | /* eslint-env es6 */ 88 | /* eslint-disable no-unused-vars */ 89 | 90 | import Axios from 'axios' 91 | import { BASE_URL } from './utils/api' 92 | import { getAPIToken } from './utils/helpers' 93 | 94 | export default class User { 95 | constructor () { 96 | this.id = null 97 | this.username = null 98 | this.email = '' 99 | this.isActive = false 100 | this.lastLogin = '' // ISO 8601 formatted timestamp. 101 | this.lastPWChange = '' // ISO 8601 formatted timestamp. 102 | } 103 | } 104 | 105 | const getUserProfile = async (id) => { 106 | let user = new User() 107 | await Axios.get( 108 | `${BASE_URL}/users/${id}`, 109 | { 110 | headers: { 111 | 'Authorization': `Token ${getAPIToken()}`, 112 | } 113 | } 114 | ).then{response => { 115 | // ... 116 | }).catch(error => { 117 | // ... 118 | }) 119 | } 120 | \end{lstlisting} 121 | ``` 122 | 123 | ### Resulting Typeset 124 | ![ES6 Listing Example](img/es6_listing_example.png) 125 | 126 | # Styling the language 127 | The `listings` package also has the built-in capacity for custom styling the language definitions. The styles presented in the typeset images were generated using: 128 | 129 | ```tex 130 | % Requires package: color. 131 | \definecolor{mediumgray}{rgb}{0.3, 0.4, 0.4} 132 | \definecolor{mediumblue}{rgb}{0.0, 0.0, 0.8} 133 | \definecolor{forestgreen}{rgb}{0.13, 0.55, 0.13} 134 | \definecolor{darkviolet}{rgb}{0.58, 0.0, 0.83} 135 | \definecolor{royalblue}{rgb}{0.25, 0.41, 0.88} 136 | \definecolor{crimson}{rgb}{0.86, 0.8, 0.24} 137 | 138 | \lstdefinestyle{JSES6Base}{ 139 | backgroundcolor=\color{white}, 140 | basicstyle=\ttfamily, 141 | breakatwhitespace=false, 142 | breaklines=false, 143 | captionpos=b, 144 | columns=fullflexible, 145 | commentstyle=\color{mediumgray}\upshape, 146 | emph={}, 147 | emphstyle=\color{crimson}, 148 | extendedchars=true, % requires inputenc 149 | fontadjust=true, 150 | frame=single, 151 | identifierstyle=\color{black}, 152 | keepspaces=true, 153 | keywordstyle=\color{mediumblue}, 154 | keywordstyle={[2]\color{darkviolet}}, 155 | keywordstyle={[3]\color{royalblue}}, 156 | numbers=left, 157 | numbersep=5pt, 158 | numberstyle=\tiny\color{black}, 159 | rulecolor=\color{black}, 160 | showlines=true, 161 | showspaces=false, 162 | showstringspaces=false, 163 | showtabs=false, 164 | stringstyle=\color{forestgreen}, 165 | tabsize=2, 166 | title=\lstname, 167 | upquote=true % requires textcomp 168 | } 169 | 170 | \lstdefinestyle{JavaScript}{ 171 | language=JavaScript, 172 | style=JSES6Base 173 | } 174 | \lstdefinestyle{ES6}{ 175 | language=ES6, 176 | style=JSES6Base 177 | } 178 | ``` -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /img/es6_listing_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghammock/LaTeX_Listings_JavaScript_ES6/e82af53fb2a9534a295ec69ae8c47ba36166beeb/img/es6_listing_example.png -------------------------------------------------------------------------------- /img/js_listing_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghammock/LaTeX_Listings_JavaScript_ES6/e82af53fb2a9534a295ec69ae8c47ba36166beeb/img/js_listing_example.png -------------------------------------------------------------------------------- /js_listing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghammock/LaTeX_Listings_JavaScript_ES6/e82af53fb2a9534a295ec69ae8c47ba36166beeb/js_listing.pdf -------------------------------------------------------------------------------- /js_listing.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt]{article} 2 | 3 | \usepackage{listings} 4 | \usepackage{color} 5 | \usepackage{textcomp} % for upquote 6 | 7 | % 8 | % ECMAScript 2015 (ES6) definition by Gary Hammock 9 | % 10 | 11 | \lstdefinelanguage[ECMAScript2015]{JavaScript}[]{JavaScript}{ 12 | morekeywords=[1]{await, async, case, catch, class, const, default, do, 13 | enum, export, extends, finally, from, implements, import, instanceof, 14 | let, static, super, switch, throw, try}, 15 | morestring=[b]` % Interpolation strings. 16 | } 17 | 18 | 19 | % 20 | % JavaScript version 1.1 by Gary Hammock 21 | % 22 | % Reference: 23 | % B. Eich and C. Rand Mckinney, "JavaScript Language Specification 24 | % (Preliminary Draft)", JavaScript 1.1. 1996-11-18. [Online] 25 | % http://hepunx.rl.ac.uk/~adye/jsspec11/titlepg2.htm 26 | % 27 | 28 | \lstdefinelanguage{JavaScript}{ 29 | morekeywords=[1]{break, continue, delete, else, for, function, if, in, 30 | new, return, this, typeof, var, void, while, with}, 31 | % Literals, primitive types, and reference types. 32 | morekeywords=[2]{false, null, true, boolean, number, undefined, 33 | Array, Boolean, Date, Math, Number, String, Object}, 34 | % Built-ins. 35 | morekeywords=[3]{eval, parseInt, parseFloat, escape, unescape}, 36 | sensitive, 37 | morecomment=[s]{/*}{*/}, 38 | morecomment=[l]//, 39 | morecomment=[s]{/**}{*/}, % JavaDoc style comments 40 | morestring=[b]', 41 | morestring=[b]" 42 | }[keywords, comments, strings] 43 | 44 | 45 | \lstalias[]{ES6}[ECMAScript2015]{JavaScript} 46 | 47 | % Requires package: color. 48 | \definecolor{mediumgray}{rgb}{0.3, 0.4, 0.4} 49 | \definecolor{mediumblue}{rgb}{0.0, 0.0, 0.8} 50 | \definecolor{forestgreen}{rgb}{0.13, 0.55, 0.13} 51 | \definecolor{darkviolet}{rgb}{0.58, 0.0, 0.83} 52 | \definecolor{royalblue}{rgb}{0.25, 0.41, 0.88} 53 | \definecolor{crimson}{rgb}{0.86, 0.8, 0.24} 54 | 55 | \lstdefinestyle{JSES6Base}{ 56 | backgroundcolor=\color{white}, 57 | basicstyle=\ttfamily, 58 | breakatwhitespace=false, 59 | breaklines=false, 60 | captionpos=b, 61 | columns=fullflexible, 62 | commentstyle=\color{mediumgray}\upshape, 63 | emph={}, 64 | emphstyle=\color{crimson}, 65 | extendedchars=true, % requires inputenc 66 | fontadjust=true, 67 | frame=single, 68 | identifierstyle=\color{black}, 69 | keepspaces=true, 70 | keywordstyle=\color{mediumblue}, 71 | keywordstyle={[2]\color{darkviolet}}, 72 | keywordstyle={[3]\color{royalblue}}, 73 | numbers=left, 74 | numbersep=5pt, 75 | numberstyle=\tiny\color{black}, 76 | rulecolor=\color{black}, 77 | showlines=true, 78 | showspaces=false, 79 | showstringspaces=false, 80 | showtabs=false, 81 | stringstyle=\color{forestgreen}, 82 | tabsize=2, 83 | title=\lstname, 84 | upquote=true % requires textcomp 85 | } 86 | 87 | \lstdefinestyle{JavaScript}{ 88 | language=JavaScript, 89 | style=JSES6Base 90 | } 91 | \lstdefinestyle{ES6}{ 92 | language=ES6, 93 | style=JSES6Base 94 | } 95 | 96 | \begin{document} 97 | 98 | 99 | \begin{lstlisting}[style=JavaScript, caption={JavaScript Listing}] 100 | (function () { 101 | var user = getCookie("username"); 102 | document.getElementById("#date-field").innerHTML = new Date(); 103 | document.getElementById("#greetings").innerHTML = 104 | "

Hello, " + user.name + ".

"; 105 | })() 106 | 107 | function getCookie(cname) { 108 | var name = cname + "="; 109 | var decodedCookie = decodeURIComponent(document.cookie); 110 | var ca = decodedCookie.split(';'); 111 | for(var i = 0; i < ca.length; ++i) { 112 | var c = ca[i]; 113 | while (c.charAt(0) == ' ') { 114 | c = c.substring(1); 115 | } 116 | if (c.indexOf(name) == 0) { 117 | return c.substring(name.length, c.length); 118 | } 119 | } 120 | return ""; 121 | } 122 | \end{lstlisting} 123 | 124 | \newpage 125 | 126 | \begin{lstlisting}[style=ES6, caption={ES6 (ECMAScript-2015) Listing}] 127 | /* eslint-env es6 */ 128 | /* eslint-disable no-unused-vars */ 129 | 130 | import Axios from 'axios' 131 | import { BASE_URL } from './utils/api' 132 | import { getAPIToken } from './utils/helpers' 133 | 134 | export default class User { 135 | constructor () { 136 | this.id = null 137 | this.username = null 138 | this.email = '' 139 | this.isActive = false 140 | this.lastLogin = '' // ISO 8601 formatted timestamp. 141 | this.lastPWChange = '' // ISO 8601 formatted timestamp. 142 | } 143 | } 144 | 145 | const getUserProfile = async (id) => { 146 | let user = new User() 147 | await Axios.get( 148 | `${BASE_URL}/users/${id}`, 149 | { 150 | headers: { 151 | 'Authorization': `Token ${getAPIToken()}`, 152 | } 153 | } 154 | ).then{response => { 155 | // ... 156 | }).catch(error => { 157 | // ... 158 | }) 159 | } 160 | \end{lstlisting} 161 | 162 | \end{document} --------------------------------------------------------------------------------