From 4fad2132b28540870497da517a0939b19a3f4b0e Mon Sep 17 00:00:00 2001 From: Saswat Padhi Date: Sat, 27 May 2023 06:39:45 +0000 Subject: [PATCH] modernize code, fix linter issues --- .eslintrc | 121 +++++++++++++------------- Makefile | 11 ++- docs/pseudocode.js | 2 +- pseudocode.js | 36 ++++---- src/Lexer.js | 55 +++++++----- src/ParseError.js | 10 +-- src/Parser.js | 99 +++++++++++++--------- src/Renderer.js | 207 ++++++++++++++++++++++----------------------- src/utils.js | 12 +-- 9 files changed, 294 insertions(+), 259 deletions(-) diff --git a/.eslintrc b/.eslintrc index e680187..d7235df 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,65 +1,66 @@ { "rules": { - "arrow-spacing": 2, - "brace-style": [2, "stroustrup", { "allowSingleLine": true }], - // We'd possibly like to remove the 'properties': 'never' one day. - "camelcase": [2, { "properties": "never" }], - "comma-dangle": [2, "always-multiline"], - "comma-spacing": [2, { "before": false, "after": true }], - "constructor-super": 2, - "curly": 0, - "eol-last": 2, - "eqeqeq": [2, "allow-null"], - "guard-for-in": 0, - "indent": [1, 4, {"CallExpression": {"arguments": "first"}, "flatTernaryExpressions": true, "SwitchCase": 1}], - "keyword-spacing": 2, - "linebreak-style": [2, "unix"], - "max-len": [2, 120, 4, { "ignoreUrls": true, "ignorePattern": "\\brequire\\([\"']|eslint-disable", "ignoreComments": true, }], - "no-alert": 2, - "no-array-constructor": 2, - "no-console": 0, - "no-const-assign": 2, - "no-constant-condition": 0, - "no-debugger": 2, - "no-dupe-class-members": 2, - "no-dupe-keys": 2, - "no-extra-bind": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-object": 2, - "no-spaced-func": 2, - "no-this-before-super": 2, - "no-throw-literal": 0, - "no-trailing-spaces": 2, - "no-undef": 0, - "no-unexpected-multiline": 2, - "no-unreachable": 2, - "no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^_*$"}], - "no-useless-call": 2, - "no-with": 2, - "one-var": [2, "never"], - "prefer-const": 2, - "prefer-spread": 0, // re-enable once we use es6 - "semi": [2, "always"], - "space-before-blocks": 2, - "space-before-function-paren": [2, "never"], - "space-infix-ops": 2, - "space-unary-ops": 2, - // --------------------------------------- - // Stuff we explicitly disable. - // We turned this off because it complains when you have a - // multi-line string, which I think is going too far. - "prefer-template": 0, - // We've decided explicitly not to care about this. - "arrow-parens": 0, - // --------------------------------------- - // TODO(csilvers): enable these if/when community agrees on it. - "prefer-arrow-callback": 0, - "object-curly-spacing": [0, "always"], - // Might be nice to turn this on one day, but since we don't - // use jsdoc anywhere it seems silly to require it yet. - "valid-jsdoc": 0, - "require-jsdoc": 0 + "arrow-spacing": "error", + "brace-style": ["error", "stroustrup"], + "camelcase": "error", + "comma-dangle": ["error", "always-multiline"], + "comma-spacing": "error", + "constructor-super": "error", + "curly": ["error", "multi-or-nest", "consistent"], + "eol-last": "error", + "eqeqeq": ["error", "always"], + "guard-for-in": "off", + "indent": ["error", 4, { + "CallExpression": {"arguments": "first"}, + "FunctionExpression": {"parameters": "first"}, + "flatTernaryExpressions": true, + "SwitchCase": 1 + }], + "keyword-spacing": "error", + "linebreak-style": ["error", "unix"], + "max-len": ["error", 128, 2, { + "ignoreUrls": true, + "ignorePattern": "\\brequire\\([\"']|eslint-disable", + "ignoreComments": true + }], + "no-alert": "error", + "no-array-constructor": "error", + "no-console": "off", + "no-const-assign": "error", + "no-constant-condition": "off", + "no-debugger": "error", + "no-dupe-class-members": "error", + "no-dupe-keys": "error", + "no-duplicate-imports": "error", + "no-extra-bind": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-spaced-func": "error", + "no-this-before-super": "error", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef": "off", + "no-unexpected-multiline": "error", + "no-unreachable": "error", + "no-unused-vars": ["error", {"args": "none", "varsIgnorePattern": "^_*$"}], + "no-useless-call": "error", + "no-with": "error", + "one-var": ["error", "never"], + "prefer-const": "error", + "prefer-spread": "error", + "semi": ["error", "always"], + "space-before-blocks": "error", + "space-before-function-paren": ["error", "always"], + "space-infix-ops": "error", + "space-unary-ops": "error", + "prefer-template": "error", + "no-template-curly-in-string": "error", + "template-curly-spacing": ["error", "never"], + "arrow-parens": ["error", "always"], + "arrow-body-style": "error", + "prefer-arrow-callback": "error", + "object-curly-spacing": ["error", "always"] }, "env": { "es6": true, diff --git a/Makefile b/Makefile index a4ee9ef..b3ab5ca 100644 --- a/Makefile +++ b/Makefile @@ -34,9 +34,6 @@ build/pseudocode.js: pseudocode.js $(wildcard src/*.js) @$(MAKE) --no-print-directory lint $(BROWSERIFY) $< --exclude mathjax --exclude katex --standalone pseudocode -o $@ -lint: pseudocode.js $(wildcard src/*.js) - $(ESLINT) $^ - build/pseudocode.css: static/pseudocode.css cp static/pseudocode.css build/pseudocode.css @@ -45,6 +42,14 @@ build/%-samples.html: static/%.html.part static/body.html.part static/footer.htm +lint: pseudocode.js $(wildcard src/*.js) + $(ESLINT) $^ + +fix-lint: pseudocode.js $(wildcard src/*.js) + $(ESLINT) --fix $^ + + + release: build docs build/pseudocode-js.tar.gz build/pseudocode-js.zip @echo "> Release package generated\n" diff --git a/docs/pseudocode.js b/docs/pseudocode.js index c1b1b38..254a7f1 100644 --- a/docs/pseudocode.js +++ b/docs/pseudocode.js @@ -1 +1 @@ -(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.pseudocode=e()}})(function(){var e,t,n;return function(){function p(o,s,a){function h(n,e){if(!s[n]){if(!o[n]){var t="function"==typeof require&&require;if(!e&&t)return t(n,!0);if(l)return l(n,!0);var i=new Error("Cannot find module '"+n+"'");throw i.code="MODULE_NOT_FOUND",i}var r=s[n]={exports:{}};o[n][0].call(r.exports,function(e){var t=o[n][1][e];return h(t||e)},r,r.exports,p,o,s,a)}return s[n].exports}for(var l="function"==typeof require&&require,e=0;e0&&a[h-1]==="\\"){var l=h+o.length;a=a.slice(l);s+=l;continue}var p=[e.slice(0,s+h+o.length),e.slice(r.length,s+h)];return p}}return null}};var p={special:/^(\\\\|\\{|\\}|\\\$|\\&|\\#|\\%|\\_)/,math:o,func:/^\\([a-zA-Z]+)/,open:/^\{/,close:/^\}/,quote:/^(`|``|'|'')/,ordinary:/^[^\\{}$&#%_\s]+/};var c=/^%.*/;var f=/^\s+/;r.prototype._skip=function(e){this._pos+=e;this._remain=this._remain.slice(e)};r.prototype._next=function(){var e=false;while(1){var t=f.exec(this._remain);if(t){e=true;var n=t[0].length;this._skip(n)}var i=c.exec(this._remain);if(!i)break;var r=i[0].length;this._skip(r)}this._currentAtom=this._nextAtom;if(this._remain===""){this._nextAtom={type:"EOF",text:null,whitespace:false};return false}for(var o in p){var s=p[o];var a=s.exec(this._remain);if(!a)continue;var h=a[0];var l=a[1]?a[1]:h;this._nextAtom={type:o,text:l,whitespace:e};this._pos+=h.length;this._remain=this._remain.slice(a[0].length);return true}throw new u("Unrecoganizable atom",this._pos,this._input)};r.prototype._matchText=function(e){if(e===null||e===undefined)return true;if(i.isString(e))return e.toLowerCase()===this._nextAtom.text.toLowerCase();else{e=e.map(function(e){return e.toLowerCase()});return e.indexOf(this._nextAtom.text.toLowerCase())>=0}};t.exports=r},{"./ParseError":3,"./utils":6}],3:[function(e,t,n){function i(e,t,n){var i="Error: "+e;if(t!==undefined&&n!==undefined){i+=" at position "+t+": `";n=n.slice(0,t)+"\u21b1"+n.slice(t);var r=Math.max(0,t-15);var o=t+15;i+=n.slice(r,o)+"`"}this.message=i}i.prototype=Object.create(Error.prototype);i.prototype.constructor=i;t.exports=i},{}],4:[function(e,t,n){var s=e("./utils");var r=e("./ParseError");var a=function(e,t){this.type=e;this.value=t;this.children=[]};a.prototype.toString=function(e){if(!e)e=0;var t="";for(var n=0;n";if(this.value)i+=" ("+s.toString(this.value)+")";i+="\n";if(this.children){for(var r=0;r0){e.addChild(t);continue}break}return e};i.prototype._parseCaption=function(){var e=this._lexer;if(!e.accept("func","caption"))return null;var t=new a("caption");e.expect("open");t.addChild(this._parseCloseText());e.expect("close");return t};i.prototype._parseBlock=function(){var e=new a("block");while(true){var t=this._parseControl();if(t){e.addChild(t);continue}var n=this._parseFunction();if(n){e.addChild(n);continue}var i=this._parseStatement(l);if(i){e.addChild(i);continue}var r=this._parseCommand(p);if(r){e.addChild(r);continue}var o=this._parseComment();if(o){e.addChild(o);continue}break}return e};i.prototype._parseControl=function(){var e;if(e=this._parseIf())return e;if(e=this._parseLoop())return e;if(e=this._parseRepeat())return e;if(e=this._parseUpon())return e};i.prototype._parseFunction=function(){var e=this._lexer;if(!e.accept("func",["function","procedure"]))return null;var t=this._lexer.get().text;e.expect("open");var n=e.expect("ordinary");e.expect("close");e.expect("open");var i=this._parseCloseText();e.expect("close");var r=this._parseBlock();e.expect("func","end"+t);var o=new a("function",{type:t,name:n});o.addChild(i);o.addChild(r);return o};i.prototype._parseIf=function(){if(!this._lexer.accept("func","if"))return null;var e=new a("if");this._lexer.expect("open");e.addChild(this._parseCond());this._lexer.expect("close");e.addChild(this._parseBlock());var t=0;while(this._lexer.accept("func",["elif","elsif","elseif"])){this._lexer.expect("open");e.addChild(this._parseCond());this._lexer.expect("close");e.addChild(this._parseBlock());t++}var n=false;if(this._lexer.accept("func","else")){n=true;e.addChild(this._parseBlock())}this._lexer.expect("func","endif");e.value={numElif:t,hasElse:n};return e};i.prototype._parseLoop=function(){if(!this._lexer.accept("func",["FOR","FORALL","WHILE"]))return null;var e=this._lexer.get().text.toLowerCase();var t=new a("loop",e);this._lexer.expect("open");t.addChild(this._parseCond());this._lexer.expect("close");t.addChild(this._parseBlock());var n=e!=="forall"?"end"+e:"endfor";this._lexer.expect("func",n);return t};i.prototype._parseRepeat=function(){if(!this._lexer.accept("func",["REPEAT"]))return null;var e=this._lexer.get().text.toLowerCase();var t=new a("repeat",e);t.addChild(this._parseBlock());this._lexer.expect("func","until");this._lexer.expect("open");t.addChild(this._parseCond());this._lexer.expect("close");return t};i.prototype._parseUpon=function(){if(!this._lexer.accept("func","upon"))return null;var e=new a("upon");this._lexer.expect("open");e.addChild(this._parseCond());this._lexer.expect("close");e.addChild(this._parseBlock());this._lexer.expect("func","endupon");return e};var h=["ensure","require","input","output"];var l=["state","print","return"];i.prototype._parseStatement=function(e){if(!this._lexer.accept("func",e))return null;var t=this._lexer.get().text.toLowerCase();var n=new a("statement",t);n.addChild(this._parseOpenText());return n};var p=["break","continue"];i.prototype._parseCommand=function(e){if(!this._lexer.accept("func",e))return null;var t=this._lexer.get().text.toLowerCase();var n=new a("command",t);return n};i.prototype._parseComment=function(){if(!this._lexer.accept("func","comment"))return null;var e=new a("comment");this._lexer.expect("open");e.addChild(this._parseCloseText());this._lexer.expect("close");return e};i.prototype._parseCall=function(){var e=this._lexer;if(!e.accept("func","call"))return null;var t=e.get().whitespace;e.expect("open");var n=e.expect("ordinary");e.expect("close");var i=new a("call");i.whitespace=t;i.value=n;e.expect("open");var r=this._parseCloseText();i.addChild(r);e.expect("close");return i};i.prototype._parseCond=i.prototype._parseCloseText=function(){return this._parseText("close")};i.prototype._parseOpenText=function(){return this._parseText("open")};i.prototype._parseText=function(e){var t=new a(e+"-text");var n=false;var i;while(true){i=this._parseAtom()||this._parseCall();if(i){if(n)i.whitespace|=n;t.addChild(i);continue}if(this._lexer.accept("open")){i=this._parseCloseText();n=this._lexer.get().whitespace;i.whitespace=n;t.addChild(i);this._lexer.expect("close");n=this._lexer.get().whitespace;continue}break}return t};var u={ordinary:{tokenType:"ordinary"},math:{tokenType:"math"},special:{tokenType:"special"},"cond-symbol":{tokenType:"func",tokenValues:["and","or","not","true","false","to","downto"]},"quote-symbol":{tokenType:"quote"},"sizing-dclr":{tokenType:"func",tokenValues:["tiny","scriptsize","footnotesize","small","normalsize","large","Large","LARGE","huge","Huge"]},"font-dclr":{tokenType:"func",tokenValues:["normalfont","rmfamily","sffamily","ttfamily","upshape","itshape","slshape","scshape","bfseries","mdseries","lfseries"]},"font-cmd":{tokenType:"func",tokenValues:["textnormal","textrm","textsf","texttt","textup","textit","textsl","textsc","uppercase","lowercase","textbf","textmd","textlf"]},"text-symbol":{tokenType:"func",tokenValues:["textbackslash"]}};i.prototype._parseAtom=function(){for(var e in u){var t=u[e];var n=this._lexer.accept(t.tokenType,t.tokenValues);if(n===null)continue;var i=this._lexer.get().whitespace;if(e!=="ordinary"&&e!=="math")n=n.toLowerCase();return new o(e,n,i)}return null};t.exports=i},{"./ParseError":3,"./utils":6}],5:[function(n,e,t){var a=n("./utils");function B(e){this._css={};this._fontSize=this._outerFontSize=e!==undefined?e:1}B.prototype.outerFontSize=function(e){if(e!==undefined)this._outerFontSize=e;return this._outerFontSize};B.prototype.fontSize=function(){return this._fontSize};B.prototype._fontCommandTable={normalfont:{"font-family":"KaTeX_Main"},rmfamily:{"font-family":"KaTeX_Main"},sffamily:{"font-family":"KaTeX_SansSerif"},ttfamily:{"font-family":"KaTeX_Typewriter"},bfseries:{"font-weight":"bold"},mdseries:{"font-weight":"medium"},lfseries:{"font-weight":"lighter"},upshape:{"font-style":"normal","font-variant":"normal"},itshape:{"font-style":"italic","font-variant":"normal"},scshape:{"font-style":"normal","font-variant":"small-caps"},slshape:{"font-style":"oblique","font-variant":"normal"},textnormal:{"font-family":"KaTeX_Main"},textrm:{"font-family":"KaTeX_Main"},textsf:{"font-family":"KaTeX_SansSerif"},texttt:{"font-family":"KaTeX_Typewriter"},textbf:{"font-weight":"bold"},textmd:{"font-weight":"medium"},textlf:{"font-weight":"lighter"},textup:{"font-style":"normal","font-variant":"normal"},textit:{"font-style":"italic","font-variant":"normal"},textsc:{"font-style":"normal","font-variant":"small-caps"},textsl:{"font-style":"oblique","font-variant":"normal"},uppercase:{"text-transform":"uppercase"},lowercase:{"text-transform":"lowercase"}};B.prototype._sizingScalesTable={tiny:.68,scriptsize:.8,footnotesize:.85,small:.92,normalsize:1,large:1.17,Large:1.41,LARGE:1.58,huge:1.9,Huge:2.28};B.prototype.updateByCommand=function(e){var t=this._fontCommandTable[e];if(t!==undefined){for(var n in t)this._css[n]=t[n];return}var i=this._sizingScalesTable[e];if(i!==undefined){this._outerFontSize=this._fontSize;this._fontSize=i;return}throw new ParserError("unrecogniazed text-style command")};B.prototype.toCSS=function(){var e="";for(var t in this._css){var n=this._css[t];if(n===undefined)continue;e+=t+":"+n+";"}if(this._fontSize!==this._outerFontSize){e+="font-size:"+this._fontSize/this._outerFontSize+"em;"}return e};function F(e,t){this._nodes=e;this._textStyle=t}F.prototype._renderCloseText=function(e,t){var n=new B(this._textStyle.fontSize());var i=new F(e.children,n);if(e.whitespace)this._html.putText(" ");this._html.putHTML(i.renderToHTML(t))};F.prototype.renderToHTML=function(e){this._html=new _;var t;while((t=this._nodes.shift())!==undefined){var n=t.type;var i=t.value;if(t.whitespace)this._html.putText(" ");switch(n){case"ordinary":this._html.putText(i);break;case"math":if(typeof e==="undefined"){throw"No math backend found. Please setup KaTeX or MathJax."}else if(e.name==="katex"){this._html.putHTML(e.driver.renderToString(i))}else if(e.name==="mathjax"){this._html.putText("$"+i+"$")}else{throw"Unknown math backend "+e}break;case"cond-symbol":this._html.beginSpan("ps-keyword").putText(i.toLowerCase()).endSpan();break;case"special":if(i==="\\\\"){this._html.putHTML("
");break}var r={"\\{":"{","\\}":"}","\\$":"$","\\&":"&","\\#":"#","\\%":"%","\\_":"_"};var o=r[i];this._html.putText(o);break;case"text-symbol":var s={textbackslash:"\\"};var a=s[i];this._html.putText(a);break;case"quote-symbol":var h={"`":"\u2018","``":"\u201c","'":"\u2019","''":"\u201d"};var l=h[i];this._html.putText(l);break;case"call":this._html.beginSpan("ps-funcname").putText(i).endSpan();this._html.write("(");var p=t.children[0];this._renderCloseText(p,e);this._html.write(")");break;case"close-text":this._renderCloseText(t,e);break;case"font-dclr":case"sizing-dclr":this._textStyle.updateByCommand(i);this._html.beginSpan(null,this._textStyle.toCSS());var u=new F(this._nodes,this._textStyle);this._html.putHTML(u.renderToHTML(e));this._html.endSpan();break;case"font-cmd":var c=this._nodes[0];if(c.type!=="close-text")continue;var f=new B(this._textStyle.fontSize());f.updateByCommand(i);this._html.beginSpan(null,f.toCSS());var d=new F(c.children,f);this._html.putHTML(d.renderToHTML(e));this._html.endSpan();break;default:throw new ParseError("Unexpected ParseNode of type "+t.type)}}return this._html.toMarkup()};function _(){this._body=[];this._textBuf=[]}_.prototype.beginDiv=function(e,t,n){this._beginTag("div",e,t,n);this._body.push("\n");return this};_.prototype.endDiv=function(){this._endTag("div");this._body.push("\n");return this};_.prototype.beginP=function(e,t,n){this._beginTag("p",e,t,n);this._body.push("\n");return this};_.prototype.endP=function(){this._flushText();this._endTag("p");this._body.push("\n");return this};_.prototype.beginSpan=function(e,t,n){this._flushText();return this._beginTag("span",e,t,n)};_.prototype.endSpan=function(){this._flushText();return this._endTag("span")};_.prototype.putHTML=function(e){this._flushText();this._body.push(e);return this};_.prototype.putText=function(e){this._textBuf.push(e);return this};_.prototype.write=function(e){this._body.push(e)};_.prototype.toMarkup=function(){this._flushText();var e=this._body.join("");return e.trim()};_.prototype.toDOM=function(){var e=this.toMarkup();var t=document.createElement("div");t.innerHTML=e;return t.firstChild};_.prototype._flushText=function(){if(this._textBuf.length===0)return;var e=this._textBuf.join("");this._body.push(this._escapeHtml(e));this._textBuf=[]};_.prototype._beginTag=function(e,t,n,i){var r="<"+e;if(t)r+=' class="'+t+'"';if(n){var o;if(a.isString(n))o=n;else{o="";for(var s in n){attrVal=n[s];o+=s+":"+attrVal+";"}}if(i)o+=i;r+=' style="'+o+'"'}r+=">";this._body.push(r);return this};_.prototype._endTag=function(e){this._body.push("");return this};var i={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};_.prototype._escapeHtml=function(e){return String(e).replace(/[&<>"'/]/g,function(e){return i[e]})};function r(e){e=e||{};this.indentSize=e.indentSize?this._parseEmVal(e.indentSize):1.2;this.commentDelimiter=e.commentDelimiter!==undefined?e.commentDelimiter:" // ";this.lineNumberPunc=e.lineNumberPunc!==undefined?e.lineNumberPunc:":";this.lineNumber=e.lineNumber!==undefined?e.lineNumber:false;this.noEnd=e.noEnd!==undefined?e.noEnd:false;this.scopeLines=e.scopeLines!==undefined?e.scopeLines:false;if(e.captionCount!==undefined)P.captionCount=e.captionCount;this.titlePrefix=e.titlePrefix!==undefined?e.titlePrefix:"Algorithm"}r.prototype._parseEmVal=function(e){e=e.trim();if(e.indexOf("em")!==e.length-2)throw"option unit error; no `em` found";return Number(e.substring(0,e.length-2))};function P(e,t){this._root=e.parse();this._options=new r(t);this._openLine=false;this._blockLevel=0;this._textLevel=-1;this._globalTextStyle=new B;this.backend=undefined;try{if(typeof katex==="undefined")katex=n("katex")}catch(e){}try{if(typeof MathJax==="undefined")MathJax=n("mathjax")}catch(e){}if(typeof katex!=="undefined"){this.backend={name:"katex",driver:katex}}else if(typeof MathJax!=="undefined"){this.backend={name:"mathjax",driver:MathJax}}}P.captionCount=0;P.prototype.toMarkup=function(){var e=this._html=new _;this._buildTree(this._root);delete this._html;return e.toMarkup()};P.prototype.toDOM=function(){var e=this.toMarkup();var t=document.createElement("div");t.innerHTML=e;return t.firstChild};P.prototype._beginGroup=function(e,t,n){this._closeLineIfAny();this._html.beginDiv("ps-"+e+(t?" "+t:""),n)};P.prototype._endGroup=function(e){this._closeLineIfAny();this._html.endDiv()};P.prototype._beginBlock=function(){var e=this._options.lineNumber&&this._blockLevel===0?.6:0;var t=this._options.indentSize+e;if(this._options.scopeLines)t/=2;this._beginGroup("block",null,{"margin-left":t+"em"});this._blockLevel++};P.prototype._endBlock=function(){this._closeLineIfAny();this._endGroup();this._blockLevel--};P.prototype._newLine=function(){this._closeLineIfAny();this._openLine=true;this._globalTextStyle.outerFontSize(1);var e=this._options.indentSize;if(this._blockLevel>0){this._numLOC++;this._html.beginP("ps-line ps-code",this._globalTextStyle.toCSS());var t=this._options.lineNumber?e*1.25:0;t+=this._options.scopeLines?e*.1:0;if(this._options.lineNumber){this._html.beginSpan("ps-linenum",{left:-((this._blockLevel-1)*t)+"em"}).putText(this._numLOC+this._options.lineNumberPunc).endSpan()}}else{this._html.beginP("ps-line",{"text-indent":-e+"em","padding-left":e+"em"},this._globalTextStyle.toCSS())}};P.prototype._closeLineIfAny=function(){if(!this._openLine)return;this._html.endP();this._openLine=false};P.prototype._typeKeyword=function(e){this._html.beginSpan("ps-keyword").putText(e).endSpan()};P.prototype._typeFuncName=function(e){this._html.beginSpan("ps-funcname").putText(e).endSpan()};P.prototype._typeText=function(e){this._html.write(e)};P.prototype._buildTreeForAllChildren=function(e){var t=e.children;for(var n=0;n0&&t[0].type==="comment"){var n=t.shift();this._buildTree(n)}};P.prototype._buildTree=function(e){var t;var n;var i;switch(e.type){case"root":this._beginGroup("root");this._buildTreeForAllChildren(e);this._endGroup();break;case"algorithm":var r;for(t=0;t0&&a[l-1]==="\\"){var h=l+o.length;a=a.slice(h);s+=h;continue}var p=[e.slice(0,s+l+o.length),e.slice(r.length,s+l)];return p}}return null}};var p={special:/^(\\\\|\\{|\\}|\\\$|\\&|\\#|\\%|\\_)/,math:o,func:/^\\([a-zA-Z]+)/,open:/^\{/,close:/^\}/,quote:/^(`|``|'|'')/,ordinary:/^[^\\{}$&#%_\s]+/};var c=/^%.*/;var f=/^\s+/;r.prototype._skip=function(e){this._pos+=e;this._remain=this._remain.slice(e)};r.prototype._next=function(){var e=false;while(1){var t=f.exec(this._remain);if(t){e=true;var n=t[0].length;this._skip(n)}var i=c.exec(this._remain);if(!i)break;var r=i[0].length;this._skip(r)}this._currentAtom=this._nextAtom;if(this._remain===""){this._nextAtom={type:"EOF",text:null,whitespace:false};return false}for(var o in p){var s=p[o];var a=s.exec(this._remain);if(!a)continue;var l=a[0];var h=a[1]?a[1]:l;this._nextAtom={type:o,text:h,whitespace:e};this._pos+=l.length;this._remain=this._remain.slice(a[0].length);return true}throw new u("Unrecoganizable atom",this._pos,this._input)};r.prototype._matchText=function(e){if(e===null||e===undefined)return true;if(i.isString(e))return e.toLowerCase()===this._nextAtom.text.toLowerCase();else return e.some(e=>e.toLowerCase()===this._nextAtom.text.toLowerCase())};t.exports=r},{"./ParseError":3,"./utils":6}],3:[function(e,t,n){function i(e,t,n){var i=`Error: ${e}`;if(t!==undefined&&n!==undefined){i+=` at position ${t}: \``;n=`${n.slice(0,t)}\u21B1${n.slice(t)}`;var r=Math.max(0,t-15);var o=t+15;i+=`${n.slice(r,o)}\``}this.message=i}i.prototype=Object.create(Error.prototype);i.prototype.constructor=i;t.exports=i},{}],4:[function(e,t,n){var s=e("./utils");var r=e("./ParseError");var a=function(e,t){this.type=e;this.value=t;this.children=[]};a.prototype.toString=function(e){if(!e)e=0;var t="";for(var n=0;n`;if(this.value)i+=` (${s.toString(this.value)})`;i+="\n";if(this.children){for(var r=0;r0){e.addChild(t);continue}break}return e};i.prototype._parseCaption=function(){var e=this._lexer;if(!e.accept("func","caption"))return null;var t=new a("caption");e.expect("open");t.addChild(this._parseCloseText());e.expect("close");return t};i.prototype._parseBlock=function(){var e=new a("block");while(true){var t=this._parseControl();if(t){e.addChild(t);continue}var n=this._parseFunction();if(n){e.addChild(n);continue}var i=this._parseStatement(h);if(i){e.addChild(i);continue}var r=this._parseCommand(p);if(r){e.addChild(r);continue}var o=this._parseComment();if(o){e.addChild(o);continue}break}return e};i.prototype._parseControl=function(){var e;if(e=this._parseIf())return e;if(e=this._parseLoop())return e;if(e=this._parseRepeat())return e;if(e=this._parseUpon())return e};i.prototype._parseFunction=function(){var e=this._lexer;if(!e.accept("func",["function","procedure"]))return null;var t=this._lexer.get().text;e.expect("open");var n=e.expect("ordinary");e.expect("close");e.expect("open");var i=this._parseCloseText();e.expect("close");var r=this._parseBlock();e.expect("func",`end${t}`);var o=new a("function",{type:t,name:n});o.addChild(i);o.addChild(r);return o};i.prototype._parseIf=function(){if(!this._lexer.accept("func","if"))return null;var e=new a("if");this._lexer.expect("open");e.addChild(this._parseCond());this._lexer.expect("close");e.addChild(this._parseBlock());var t=0;while(this._lexer.accept("func",["elif","elsif","elseif"])){this._lexer.expect("open");e.addChild(this._parseCond());this._lexer.expect("close");e.addChild(this._parseBlock());t++}var n=false;if(this._lexer.accept("func","else")){n=true;e.addChild(this._parseBlock())}this._lexer.expect("func","endif");e.value={numElif:t,hasElse:n};return e};i.prototype._parseLoop=function(){if(!this._lexer.accept("func",["FOR","FORALL","WHILE"]))return null;var e=this._lexer.get().text.toLowerCase();var t=new a("loop",e);this._lexer.expect("open");t.addChild(this._parseCond());this._lexer.expect("close");t.addChild(this._parseBlock());var n=e!=="forall"?`end${e}`:"endfor";this._lexer.expect("func",n);return t};i.prototype._parseRepeat=function(){if(!this._lexer.accept("func",["REPEAT"]))return null;var e=this._lexer.get().text.toLowerCase();var t=new a("repeat",e);t.addChild(this._parseBlock());this._lexer.expect("func","until");this._lexer.expect("open");t.addChild(this._parseCond());this._lexer.expect("close");return t};i.prototype._parseUpon=function(){if(!this._lexer.accept("func","upon"))return null;var e=new a("upon");this._lexer.expect("open");e.addChild(this._parseCond());this._lexer.expect("close");e.addChild(this._parseBlock());this._lexer.expect("func","endupon");return e};var l=["ensure","require","input","output"];var h=["state","print","return"];i.prototype._parseStatement=function(e){if(!this._lexer.accept("func",e))return null;var t=this._lexer.get().text.toLowerCase();var n=new a("statement",t);n.addChild(this._parseOpenText());return n};var p=["break","continue"];i.prototype._parseCommand=function(e){if(!this._lexer.accept("func",e))return null;var t=this._lexer.get().text.toLowerCase();var n=new a("command",t);return n};i.prototype._parseComment=function(){if(!this._lexer.accept("func","comment"))return null;var e=new a("comment");this._lexer.expect("open");e.addChild(this._parseCloseText());this._lexer.expect("close");return e};i.prototype._parseCall=function(){var e=this._lexer;if(!e.accept("func","call"))return null;var t=e.get().whitespace;e.expect("open");var n=e.expect("ordinary");e.expect("close");var i=new a("call");i.whitespace=t;i.value=n;e.expect("open");var r=this._parseCloseText();i.addChild(r);e.expect("close");return i};i.prototype._parseCond=i.prototype._parseCloseText=function(){return this._parseText("close")};i.prototype._parseOpenText=function(){return this._parseText("open")};i.prototype._parseText=function(e){var t=new a(`${e}-text`);var n=false;var i;while(true){i=this._parseAtom()||this._parseCall();if(i){if(n)i.whitespace|=n;t.addChild(i);continue}if(this._lexer.accept("open")){i=this._parseCloseText();n=this._lexer.get().whitespace;i.whitespace=n;t.addChild(i);this._lexer.expect("close");n=this._lexer.get().whitespace;continue}break}return t};var u={ordinary:{tokenType:"ordinary"},math:{tokenType:"math"},special:{tokenType:"special"},"cond-symbol":{tokenType:"func",tokenValues:["and","or","not","true","false","to","downto"]},"quote-symbol":{tokenType:"quote"},"sizing-dclr":{tokenType:"func",tokenValues:["tiny","scriptsize","footnotesize","small","normalsize","large","Large","LARGE","huge","Huge"]},"font-dclr":{tokenType:"func",tokenValues:["normalfont","rmfamily","sffamily","ttfamily","upshape","itshape","slshape","scshape","bfseries","mdseries","lfseries"]},"font-cmd":{tokenType:"func",tokenValues:["textnormal","textrm","textsf","texttt","textup","textit","textsl","textsc","uppercase","lowercase","textbf","textmd","textlf"]},"text-symbol":{tokenType:"func",tokenValues:["textbackslash"]}};i.prototype._parseAtom=function(){for(var e in u){var t=u[e];var n=this._lexer.accept(t.tokenType,t.tokenValues);if(n===null)continue;var i=this._lexer.get().whitespace;if(e!=="ordinary"&&e!=="math")n=n.toLowerCase();return new o(e,n,i)}return null};t.exports=i},{"./ParseError":3,"./utils":6}],5:[function(n,e,t){var a=n("./utils");function A(e){this._css={};this._fontSize=this._outerFontSize=e!==undefined?e:1}A.prototype.outerFontSize=function(e){if(e!==undefined)this._outerFontSize=e;return this._outerFontSize};A.prototype.fontSize=function(){return this._fontSize};A.prototype._fontCommandTable={normalfont:{"font-family":"KaTeX_Main"},rmfamily:{"font-family":"KaTeX_Main"},sffamily:{"font-family":"KaTeX_SansSerif"},ttfamily:{"font-family":"KaTeX_Typewriter"},bfseries:{"font-weight":"bold"},mdseries:{"font-weight":"medium"},lfseries:{"font-weight":"lighter"},upshape:{"font-style":"normal","font-variant":"normal"},itshape:{"font-style":"italic","font-variant":"normal"},scshape:{"font-style":"normal","font-variant":"small-caps"},slshape:{"font-style":"oblique","font-variant":"normal"},textnormal:{"font-family":"KaTeX_Main"},textrm:{"font-family":"KaTeX_Main"},textsf:{"font-family":"KaTeX_SansSerif"},texttt:{"font-family":"KaTeX_Typewriter"},textbf:{"font-weight":"bold"},textmd:{"font-weight":"medium"},textlf:{"font-weight":"lighter"},textup:{"font-style":"normal","font-variant":"normal"},textit:{"font-style":"italic","font-variant":"normal"},textsc:{"font-style":"normal","font-variant":"small-caps"},textsl:{"font-style":"oblique","font-variant":"normal"},uppercase:{"text-transform":"uppercase"},lowercase:{"text-transform":"lowercase"}};A.prototype._sizingScalesTable={tiny:.68,scriptsize:.8,footnotesize:.85,small:.92,normalsize:1,large:1.17,Large:1.41,LARGE:1.58,huge:1.9,Huge:2.28};A.prototype.updateByCommand=function(e){var t=this._fontCommandTable[e];if(t!==undefined){for(var n in t)this._css[n]=t[n];return}var i=this._sizingScalesTable[e];if(i!==undefined){this._outerFontSize=this._fontSize;this._fontSize=i;return}throw new ParserError("Unrecognized `text-style` command")};A.prototype.toCSS=function(){var e="";for(var t in this._css){var n=this._css[t];if(n===undefined)continue;e+=`${t}:${n};`}if(this._fontSize!==this._outerFontSize)e+=`font-size:${this._fontSize/this._outerFontSize}em;`;return e};function B(e,t){this._nodes=e;this._textStyle=t}B.prototype._renderCloseText=function(e,t){var n=new A(this._textStyle.fontSize());var i=new B(e.children,n);if(e.whitespace)this._html.putText(" ");this._html.putHTML(i.renderToHTML(t))};B.prototype.renderToHTML=function(e){this._html=new _;var t;while((t=this._nodes.shift())!==undefined){var n=t.type;var i=t.value;if(t.whitespace)this._html.putText(" ");switch(n){case"ordinary":this._html.putText(i);break;case"math":if(typeof e==="undefined")throw EvalError("No math backend found. Please setup KaTeX or MathJax.");else if(e.name==="katex")this._html.putHTML(e.driver.renderToString(i));else if(e.name==="mathjax")this._html.putText(`$${i}$`);else throw new EvalError(`Unknown math backend ${e}`);break;case"cond-symbol":this._html.beginSpan("ps-keyword").putText(i.toLowerCase()).endSpan();break;case"special":if(i==="\\\\"){this._html.putHTML("
");break}var r={"\\{":"{","\\}":"}","\\$":"$","\\&":"&","\\#":"#","\\%":"%","\\_":"_"};var o=r[i];this._html.putText(o);break;case"text-symbol":var s={textbackslash:"\\"};var a=s[i];this._html.putText(a);break;case"quote-symbol":var l={"`":"\u2018","``":"\u201c","'":"\u2019","''":"\u201d"};var h=l[i];this._html.putText(h);break;case"call":this._html.beginSpan("ps-funcname").putText(i).endSpan();this._html.write("(");var p=t.children[0];this._renderCloseText(p,e);this._html.write(")");break;case"close-text":this._renderCloseText(t,e);break;case"font-dclr":case"sizing-dclr":this._textStyle.updateByCommand(i);this._html.beginSpan(null,this._textStyle.toCSS());var u=new B(this._nodes,this._textStyle);this._html.putHTML(u.renderToHTML(e));this._html.endSpan();break;case"font-cmd":var c=this._nodes[0];if(c.type!=="close-text")continue;var f=new A(this._textStyle.fontSize());f.updateByCommand(i);this._html.beginSpan(null,f.toCSS());var d=new B(c.children,f);this._html.putHTML(d.renderToHTML(e));this._html.endSpan();break;default:throw new ParseError(`Unexpected ParseNode of type ${t.type}`)}}return this._html.toMarkup()};function _(){this._body=[];this._textBuf=[]}_.prototype.beginDiv=function(e,t,n){this._beginTag("div",e,t,n);this._body.push("\n");return this};_.prototype.endDiv=function(){this._endTag("div");this._body.push("\n");return this};_.prototype.beginP=function(e,t,n){this._beginTag("p",e,t,n);this._body.push("\n");return this};_.prototype.endP=function(){this._flushText();this._endTag("p");this._body.push("\n");return this};_.prototype.beginSpan=function(e,t,n){this._flushText();return this._beginTag("span",e,t,n)};_.prototype.endSpan=function(){this._flushText();return this._endTag("span")};_.prototype.putHTML=function(e){this._flushText();this._body.push(e);return this};_.prototype.putText=function(e){this._textBuf.push(e);return this};_.prototype.write=function(e){this._body.push(e)};_.prototype.toMarkup=function(){this._flushText();var e=this._body.join("");return e.trim()};_.prototype.toDOM=function(){var e=this.toMarkup();var t=document.createElement("div");t.innerHTML=e;return t.firstChild};_.prototype._flushText=function(){if(this._textBuf.length===0)return;var e=this._textBuf.join("");this._body.push(this._escapeHtml(e));this._textBuf=[]};_.prototype._beginTag=function(e,t,n,i){var r=`<${e}`;if(t)r+=` class="${t}"`;if(n){var o;if(a.isString(n)){o=n}else{o="";for(var s in n){attrVal=n[s];o+=`${s}:${attrVal};`}}if(i)o+=i;r+=` style="${o}"`}r+=">";this._body.push(r);return this};_.prototype._endTag=function(e){this._body.push(``);return this};var i={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};_.prototype._escapeHtml=function(e){return String(e).replace(/[&<>"'/]/g,e=>i[e])};function r(e){e=e||{};this.indentSize=e.indentSize?this._parseEmVal(e.indentSize):1.2;this.commentDelimiter=e.commentDelimiter!==undefined?e.commentDelimiter:" // ";this.lineNumberPunc=e.lineNumberPunc!==undefined?e.lineNumberPunc:":";this.lineNumber=e.lineNumber!==undefined?e.lineNumber:false;this.noEnd=e.noEnd!==undefined?e.noEnd:false;this.scopeLines=e.scopeLines!==undefined?e.scopeLines:false;if(e.captionCount!==undefined)F.captionCount=e.captionCount;this.titlePrefix=e.titlePrefix!==undefined?e.titlePrefix:"Algorithm"}r.prototype._parseEmVal=function(e){e=e.trim();if(e.indexOf("em")!==e.length-2)throw new TypeError("Unit error; expected `em` suffix");return Number(e.substring(0,e.length-2))};function F(e,t){this._root=e.parse();this._options=new r(t);this._openLine=false;this._blockLevel=0;this._textLevel=-1;this._globalTextStyle=new A;this.backend=undefined;try{if(typeof katex==="undefined")katex=n("katex")}catch(e){}try{if(typeof MathJax==="undefined")MathJax=n("mathjax")}catch(e){}if(typeof katex!=="undefined"){this.backend={name:"katex",driver:katex}}else if(typeof MathJax!=="undefined"){this.backend={name:"mathjax",driver:MathJax}}}F.captionCount=0;F.prototype.toMarkup=function(){var e=this._html=new _;this._buildTree(this._root);delete this._html;return e.toMarkup()};F.prototype.toDOM=function(){var e=this.toMarkup();var t=document.createElement("div");t.innerHTML=e;return t.firstChild};F.prototype._beginGroup=function(e,t,n){this._closeLineIfAny();this._html.beginDiv(`ps-${e}${t?` ${t}`:""}`,n)};F.prototype._endGroup=function(e){this._closeLineIfAny();this._html.endDiv()};F.prototype._beginBlock=function(){var e=this._options.lineNumber&&this._blockLevel===0?.6:0;var t=this._options.indentSize+e;if(this._options.scopeLines)t/=2;this._beginGroup("block",null,{"margin-left":`${t}em`});this._blockLevel++};F.prototype._endBlock=function(){this._closeLineIfAny();this._endGroup();this._blockLevel--};F.prototype._newLine=function(){this._closeLineIfAny();this._openLine=true;this._globalTextStyle.outerFontSize(1);var e=this._options.indentSize;if(this._blockLevel>0){this._numLOC++;this._html.beginP("ps-line ps-code",this._globalTextStyle.toCSS());var t=this._options.lineNumber?e*1.25:0;t+=this._options.scopeLines?e*.1:0;if(this._options.lineNumber){this._html.beginSpan("ps-linenum",{left:`${-((this._blockLevel-1)*t)}em`}).putText(this._numLOC+this._options.lineNumberPunc).endSpan()}}else{this._html.beginP("ps-line",{"text-indent":`${-e}em`,"padding-left":`${e}em`},this._globalTextStyle.toCSS())}};F.prototype._closeLineIfAny=function(){if(!this._openLine)return;this._html.endP();this._openLine=false};F.prototype._typeKeyword=function(e){this._html.beginSpan("ps-keyword").putText(e).endSpan()};F.prototype._typeFuncName=function(e){this._html.beginSpan("ps-funcname").putText(e).endSpan()};F.prototype._typeText=function(e){this._html.write(e)};F.prototype._buildTreeForAllChildren=function(e){var t=e.children;for(var n=0;n0&&t[0].type==="comment"){var n=t.shift();this._buildTree(n)}};F.prototype._buildTree=function(e){var t;var n;var i;switch(e.type){case"root":this._beginGroup("root");this._buildTreeForAllChildren(e);this._endGroup();break;case"algorithm":var r;for(t=0;t 0 && remain[pos - 1] === '\\') { @@ -95,13 +104,13 @@ var atomRegex = { var commentRegex = /^%.*/; var whitespaceRegex = /^\s+/; -Lexer.prototype._skip = function(len) { +Lexer.prototype._skip = function (len) { this._pos += len; this._remain = this._remain.slice(len); }; /* Get the next atom */ -Lexer.prototype._next = function() { +Lexer.prototype._next = function () { var anyWhitespace = false; while (1) { // Skip whitespace (one or more) @@ -159,17 +168,17 @@ Lexer.prototype._next = function() { }; /* Check whether the text of the next atom matches */ -Lexer.prototype._matchText = function(text) { +Lexer.prototype._matchText = function (text) { // don't need to match if (text === null || text === undefined) return true; - // string comparisons are case-insensitive - if (utils.isString(text)) // is a string, exactly the same? + // using case-insensitive comparisons, + // check if text is the same as next atom, + // or if text is an array that contains the next atom + if (utils.isString(text)) return text.toLowerCase() === this._nextAtom.text.toLowerCase(); - else {// is a list, match any of them? - text = text.map(function(str) { return str.toLowerCase(); }); - return text.indexOf(this._nextAtom.text.toLowerCase()) >= 0; - } + else + return text.some((str) => str.toLowerCase() === this._nextAtom.text.toLowerCase()); }; module.exports = Lexer; diff --git a/src/ParseError.js b/src/ParseError.js index e3ec0ad..bd30b59 100644 --- a/src/ParseError.js +++ b/src/ParseError.js @@ -1,16 +1,16 @@ -function ParseError(message, pos, input) { - var error = 'Error: ' + message; +function ParseError (message, pos, input) { + var error = `Error: ${message}`; // If we have the input and a position, make the error a bit fancier if (pos !== undefined && input !== undefined) { - error += " at position " + pos + ": `"; + error += ` at position ${pos}: \``; // Insert a combining underscore at the correct position - input = input.slice(0, pos) + "\u21B1" + input.slice(pos); + input = `${input.slice(0, pos)}\u21B1${input.slice(pos)}`; // Extract some context from the input and add it to the error var begin = Math.max(0, pos - 15); var end = pos + 15; - error += input.slice(begin, end) + "`"; + error += `${input.slice(begin, end)}\``; } this.message = error; diff --git a/src/Parser.js b/src/Parser.js index 83e5a38..7e71acd 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -88,20 +88,20 @@ var utils = require('./utils'); var ParseError = require('./ParseError'); -var ParseNode = function(type, val) { +var ParseNode = function (type, val) { this.type = type; this.value = val; this.children = []; }; -ParseNode.prototype.toString = function(level) { +ParseNode.prototype.toString = function (level) { if (!level) level = 0; var indent = ''; for (var i = 0; i < level; i++) indent += ' '; - var res = indent + '<' + this.type + '>'; - if (this.value) res += ' (' + utils.toString(this.value) + ')'; + var res = `${indent}<${this.type}>`; + if (this.value) res += ` (${utils.toString(this.value)})`; res += '\n'; if (this.children) { @@ -114,13 +114,15 @@ ParseNode.prototype.toString = function(level) { return res; }; -ParseNode.prototype.addChild = function(childNode) { - if (!childNode) throw 'argument cannot be null'; +ParseNode.prototype.addChild = function (childNode) { + if (!childNode) + throw new Error('Argument must not be null'); + this.children.push(childNode); }; /* AtomNode is the leaf node of parse tree */ -var AtomNode = function(type, value, whitespace) { +var AtomNode = function (type, value, whitespace) { // ParseNode.call(this, type, val); this.type = type; this.value = value; @@ -129,11 +131,11 @@ var AtomNode = function(type, value, whitespace) { }; AtomNode.prototype = ParseNode.prototype; -var Parser = function(lexer) { +var Parser = function (lexer) { this._lexer = lexer; }; -Parser.prototype.parse = function() { +Parser.prototype.parse = function () { var root = new ParseNode('root'); while (true) { @@ -146,7 +148,7 @@ Parser.prototype.parse = function() { else if (envName === 'algorithmic') envNode = this._parseAlgorithmicInner(); else - throw new ParseError('Unexpected environment ' + envName); + throw new ParseError(`Unexpected environment ${envName}`); this._closeEnvironment(envName); root.addChild(envNode); @@ -155,7 +157,7 @@ Parser.prototype.parse = function() { return root; }; -Parser.prototype._acceptEnvironment = function() { +Parser.prototype._acceptEnvironment = function () { var lexer = this._lexer; // \begin{XXXXX} if (!lexer.accept('func', 'begin')) return null; @@ -166,7 +168,7 @@ Parser.prototype._acceptEnvironment = function() { return envName; }; -Parser.prototype._closeEnvironment = function(envName) { +Parser.prototype._closeEnvironment = function (envName) { // \close{XXXXX} var lexer = this._lexer; lexer.expect('func', 'end'); @@ -175,13 +177,13 @@ Parser.prototype._closeEnvironment = function(envName) { lexer.expect('close'); }; -Parser.prototype._parseAlgorithmInner = function() { +Parser.prototype._parseAlgorithmInner = function () { var algNode = new ParseNode('algorithm'); while (true) { var envName = this._acceptEnvironment(); if (envName !== null) { if (envName !== 'algorithmic') - throw new ParseError('Unexpected environment ' + envName); + throw new ParseError(`Unexpected environment ${envName}`); var algmicNode = this._parseAlgorithmicInner(); this._closeEnvironment(); algNode.addChild(algmicNode); @@ -199,7 +201,7 @@ Parser.prototype._parseAlgorithmInner = function() { return algNode; }; -Parser.prototype._parseAlgorithmicInner = function() { +Parser.prototype._parseAlgorithmicInner = function () { var algmicNode = new ParseNode('algorithmic'); var node; while (true) { @@ -220,7 +222,7 @@ Parser.prototype._parseAlgorithmicInner = function() { return algmicNode; }; -Parser.prototype._parseCaption = function() { +Parser.prototype._parseCaption = function () { var lexer = this._lexer; if (!lexer.accept('func', 'caption')) return null; @@ -232,24 +234,39 @@ Parser.prototype._parseCaption = function() { return captionNode; }; -Parser.prototype._parseBlock = function() { +Parser.prototype._parseBlock = function () { var blockNode = new ParseNode('block'); while (true) { var controlNode = this._parseControl(); - if (controlNode) { blockNode.addChild(controlNode); continue; } + if (controlNode) { + blockNode.addChild(controlNode); + continue; + } var functionNode = this._parseFunction(); - if (functionNode) { blockNode.addChild(functionNode); continue; } + if (functionNode) { + blockNode.addChild(functionNode); + continue; + } var statementNode = this._parseStatement(STATEMENTS); - if (statementNode) { blockNode.addChild(statementNode); continue; } + if (statementNode) { + blockNode.addChild(statementNode); + continue; + } var commandNode = this._parseCommand(COMMANDS); - if (commandNode) { blockNode.addChild(commandNode); continue; } + if (commandNode) { + blockNode.addChild(commandNode); + continue; + } var commentNode = this._parseComment(); - if (commentNode) { blockNode.addChild(commentNode); continue; } + if (commentNode) { + blockNode.addChild(commentNode); + continue; + } break; } @@ -257,7 +274,7 @@ Parser.prototype._parseBlock = function() { return blockNode; }; -Parser.prototype._parseControl = function() { +Parser.prototype._parseControl = function () { var controlNode; if ((controlNode = this._parseIf())) return controlNode; if ((controlNode = this._parseLoop())) return controlNode; @@ -265,7 +282,7 @@ Parser.prototype._parseControl = function() { if ((controlNode = this._parseUpon())) return controlNode; }; -Parser.prototype._parseFunction = function() { +Parser.prototype._parseFunction = function () { var lexer = this._lexer; if (!lexer.accept('func', ['function', 'procedure'])) return null; @@ -280,16 +297,16 @@ Parser.prototype._parseFunction = function() { // var blockNode = this._parseBlock(); // \ENDFUNCTION - lexer.expect('func', 'end' + funcType); + lexer.expect('func', `end${funcType}`); var functionNode = new ParseNode('function', - {type: funcType, name: funcName}); + { type: funcType, name: funcName }); functionNode.addChild(argsNode); functionNode.addChild(blockNode); return functionNode; }; -Parser.prototype._parseIf = function() { +Parser.prototype._parseIf = function () { if (!this._lexer.accept('func', 'if')) return null; var ifNode = new ParseNode('if'); @@ -320,11 +337,11 @@ Parser.prototype._parseIf = function() { // \ENDIF this._lexer.expect('func', 'endif'); - ifNode.value = {numElif: numElif, hasElse: hasElse}; + ifNode.value = { numElif: numElif, hasElse: hasElse }; return ifNode; }; -Parser.prototype._parseLoop = function() { +Parser.prototype._parseLoop = function () { if (!this._lexer.accept('func', ['FOR', 'FORALL', 'WHILE'])) return null; var loopName = this._lexer.get().text.toLowerCase(); @@ -337,13 +354,13 @@ Parser.prototype._parseLoop = function() { loopNode.addChild(this._parseBlock()); // \ENDFOR - var endLoop = loopName !== 'forall' ? 'end' + loopName : 'endfor'; + var endLoop = loopName !== 'forall' ? `end${loopName}` : 'endfor'; this._lexer.expect('func', endLoop); return loopNode; }; -Parser.prototype._parseRepeat = function() { +Parser.prototype._parseRepeat = function () { if (!this._lexer.accept('func', ['REPEAT'])) return null; var repeatName = this._lexer.get().text.toLowerCase(); @@ -363,7 +380,7 @@ Parser.prototype._parseRepeat = function() { return repeatNode; }; -Parser.prototype._parseUpon = function() { +Parser.prototype._parseUpon = function () { if (!this._lexer.accept('func', 'upon')) return null; var uponNode = new ParseNode('upon'); @@ -382,7 +399,7 @@ Parser.prototype._parseUpon = function() { var IO_STATEMENTS = ['ensure', 'require', 'input', 'output']; var STATEMENTS = ['state', 'print', 'return']; -Parser.prototype._parseStatement = function(acceptStatements) { +Parser.prototype._parseStatement = function (acceptStatements) { if (!this._lexer.accept('func', acceptStatements)) return null; var stmtName = this._lexer.get().text.toLowerCase(); @@ -394,7 +411,7 @@ Parser.prototype._parseStatement = function(acceptStatements) { }; var COMMANDS = ['break', 'continue']; -Parser.prototype._parseCommand = function(acceptCommands) { +Parser.prototype._parseCommand = function (acceptCommands) { if (!this._lexer.accept('func', acceptCommands)) return null; var cmdName = this._lexer.get().text.toLowerCase(); @@ -403,7 +420,7 @@ Parser.prototype._parseCommand = function(acceptCommands) { return cmdNode; }; -Parser.prototype._parseComment = function() { +Parser.prototype._parseComment = function () { if (!this._lexer.accept('func', 'comment')) return null; var commentNode = new ParseNode('comment'); @@ -416,7 +433,7 @@ Parser.prototype._parseComment = function() { return commentNode; }; -Parser.prototype._parseCall = function() { +Parser.prototype._parseCall = function () { var lexer = this._lexer; if (!lexer.accept('func', 'call')) return null; @@ -439,15 +456,15 @@ Parser.prototype._parseCall = function() { }; Parser.prototype._parseCond = -Parser.prototype._parseCloseText = function() { +Parser.prototype._parseCloseText = function () { return this._parseText('close'); }; -Parser.prototype._parseOpenText = function() { +Parser.prototype._parseOpenText = function () { return this._parseText('open'); }; -Parser.prototype._parseText = function(openOrClose) { - var textNode = new ParseNode(openOrClose + '-text'); +Parser.prototype._parseText = function (openOrClose) { + var textNode = new ParseNode(`${openOrClose}-text`); // any whitespace between Atom and CloseText var anyWhitespace = false; var subTextNode; @@ -514,7 +531,7 @@ var ACCEPTED_TOKEN_BY_ATOM = { }, }; -Parser.prototype._parseAtom = function() { +Parser.prototype._parseAtom = function () { for (var atomType in ACCEPTED_TOKEN_BY_ATOM) { var acceptToken = ACCEPTED_TOKEN_BY_ATOM[atomType]; var tokenText = this._lexer.accept(acceptToken.tokenType, diff --git a/src/Renderer.js b/src/Renderer.js index f42e65a..3475757 100644 --- a/src/Renderer.js +++ b/src/Renderer.js @@ -21,7 +21,7 @@ var utils = require('./utils'); * \tiny, \scriptsize, \footnotesize, \small, \normalsize, * \large, \Large, \LARGE, \huge, \Huge. **/ -function TextStyle(outerFontSize) { +function TextStyle (outerFontSize) { this._css = {}; this._fontSize = this._outerFontSize = @@ -34,12 +34,12 @@ function TextStyle(outerFontSize) { * As we use relative font size 'em', the outer span (has its own TextStyle * object) affects the size of the span to which this TextStyle object attached. * */ -TextStyle.prototype.outerFontSize = function(size) { +TextStyle.prototype.outerFontSize = function (size) { if (size !== undefined) this._outerFontSize = size; return this._outerFontSize; }; -TextStyle.prototype.fontSize = function() { +TextStyle.prototype.fontSize = function () { return this._fontSize; }; @@ -49,37 +49,37 @@ TextStyle.prototype.fontSize = function() { TextStyle.prototype._fontCommandTable = { // -------------- declaration -------------- // font-family - normalfont: { 'font-family': 'KaTeX_Main'}, - rmfamily: { 'font-family': 'KaTeX_Main'}, - sffamily: { 'font-family': 'KaTeX_SansSerif'}, - ttfamily: { 'font-family': 'KaTeX_Typewriter'}, + normalfont: { 'font-family': 'KaTeX_Main' }, + rmfamily: { 'font-family': 'KaTeX_Main' }, + sffamily: { 'font-family': 'KaTeX_SansSerif' }, + ttfamily: { 'font-family': 'KaTeX_Typewriter' }, // weight - bfseries: { 'font-weight': 'bold'}, - mdseries: { 'font-weight': 'medium'}, - lfseries: { 'font-weight': 'lighter'}, + bfseries: { 'font-weight': 'bold' }, + mdseries: { 'font-weight': 'medium' }, + lfseries: { 'font-weight': 'lighter' }, // shape - upshape: { 'font-style': 'normal', 'font-variant': 'normal'}, - itshape: { 'font-style': 'italic', 'font-variant': 'normal'}, - scshape: { 'font-style': 'normal', 'font-variant': 'small-caps'}, - slshape: { 'font-style': 'oblique', 'font-variant': 'normal'}, + upshape: { 'font-style': 'normal', 'font-variant': 'normal' }, + itshape: { 'font-style': 'italic', 'font-variant': 'normal' }, + scshape: { 'font-style': 'normal', 'font-variant': 'small-caps' }, + slshape: { 'font-style': 'oblique', 'font-variant': 'normal' }, // -------------- command -------------- // font-family - textnormal: { 'font-family': 'KaTeX_Main'}, - textrm: { 'font-family': 'KaTeX_Main'}, - textsf: { 'font-family': 'KaTeX_SansSerif'}, - texttt: { 'font-family': 'KaTeX_Typewriter'}, + textnormal: { 'font-family': 'KaTeX_Main' }, + textrm: { 'font-family': 'KaTeX_Main' }, + textsf: { 'font-family': 'KaTeX_SansSerif' }, + texttt: { 'font-family': 'KaTeX_Typewriter' }, // weight - textbf: { 'font-weight': 'bold'}, - textmd: { 'font-weight': 'medium'}, - textlf: { 'font-weight': 'lighter'}, + textbf: { 'font-weight': 'bold' }, + textmd: { 'font-weight': 'medium' }, + textlf: { 'font-weight': 'lighter' }, // shape - textup: { 'font-style': 'normal', 'font-variant': 'normal'}, - textit: { 'font-style': 'italic', 'font-variant': 'normal'}, - textsc: { 'font-style': 'normal', 'font-variant': 'small-caps'}, - textsl: { 'font-style': 'oblique', 'font-variant': 'normal'}, + textup: { 'font-style': 'normal', 'font-variant': 'normal' }, + textit: { 'font-style': 'italic', 'font-variant': 'normal' }, + textsc: { 'font-style': 'normal', 'font-variant': 'small-caps' }, + textsl: { 'font-style': 'oblique', 'font-variant': 'normal' }, // case - uppercase: { 'text-transform': 'uppercase'}, - lowercase: { 'text-transform': 'lowercase'}, + uppercase: { 'text-transform': 'uppercase' }, + lowercase: { 'text-transform': 'lowercase' }, }; TextStyle.prototype._sizingScalesTable = { @@ -95,7 +95,7 @@ TextStyle.prototype._sizingScalesTable = { Huge: 2.28, }; -TextStyle.prototype.updateByCommand = function(cmd) { +TextStyle.prototype.updateByCommand = function (cmd) { // Font command var cmdStyles = this._fontCommandTable[cmd]; if (cmdStyles !== undefined) { @@ -112,19 +112,19 @@ TextStyle.prototype.updateByCommand = function(cmd) { return; } - throw new ParserError('unrecogniazed text-style command'); + throw new ParserError('Unrecognized `text-style` command'); }; -TextStyle.prototype.toCSS = function() { +TextStyle.prototype.toCSS = function () { var cssStr = ''; for (var attr in this._css) { var val = this._css[attr]; if (val === undefined) continue; - cssStr += attr + ':' + val + ';'; - } - if (this._fontSize !== this._outerFontSize) { - cssStr += 'font-size:' + (this._fontSize / this._outerFontSize) + 'em;'; + cssStr += `${attr}:${val};`; } + if (this._fontSize !== this._outerFontSize) + cssStr += `font-size:${this._fontSize / this._outerFontSize}em;`; + return cssStr; }; @@ -132,19 +132,19 @@ TextStyle.prototype.toCSS = function() { * TextEnvironment - renders the children nodes in a ParseNode of type * 'close-text' or 'open-text' to HTML. **/ -function TextEnvironment(nodes, textStyle) { +function TextEnvironment (nodes, textStyle) { this._nodes = nodes; this._textStyle = textStyle; } -TextEnvironment.prototype._renderCloseText = function(node, backend) { +TextEnvironment.prototype._renderCloseText = function (node, backend) { var newTextStyle = new TextStyle(this._textStyle.fontSize()); var closeTextEnv = new TextEnvironment(node.children, newTextStyle); if (node.whitespace) this._html.putText(' '); this._html.putHTML(closeTextEnv.renderToHTML(backend)); }; -TextEnvironment.prototype.renderToHTML = function(backend) { +TextEnvironment.prototype.renderToHTML = function (backend) { this._html = new HTMLBuilder(); var node; @@ -160,19 +160,14 @@ TextEnvironment.prototype.renderToHTML = function(backend) { this._html.putText(text); break; case 'math': - if (typeof backend === 'undefined') { - throw 'No math backend found. Please setup KaTeX or MathJax.'; - } - else if (backend.name === 'katex') { + if (typeof backend === 'undefined') + throw EvalError('No math backend found. Please setup KaTeX or MathJax.'); + else if (backend.name === 'katex') this._html.putHTML(backend.driver.renderToString(text)); - } - else if (backend.name === 'mathjax') { - this._html.putText('$' + text + '$'); - } - else { - throw 'Unknown math backend ' + backend; - } - + else if (backend.name === 'mathjax') + this._html.putText(`$${text}$`); + else + throw new EvalError(`Unknown math backend ${backend}`); break; case 'cond-symbol': this._html @@ -267,7 +262,7 @@ TextEnvironment.prototype.renderToHTML = function(backend) { this._html.endSpan(); break; default: - throw new ParseError('Unexpected ParseNode of type ' + node.type); + throw new ParseError(`Unexpected ParseNode of type ${node.type}`); } } @@ -275,75 +270,75 @@ TextEnvironment.prototype.renderToHTML = function(backend) { }; /* HTMLBuilder - A helper class for constructing HTML */ -function HTMLBuilder() { +function HTMLBuilder () { this._body = []; this._textBuf = []; } -HTMLBuilder.prototype.beginDiv = function(className, style, extraStyle) { +HTMLBuilder.prototype.beginDiv = function (className, style, extraStyle) { this._beginTag('div', className, style, extraStyle); this._body.push('\n'); // make the generated HTML more human friendly return this; }; -HTMLBuilder.prototype.endDiv = function() { +HTMLBuilder.prototype.endDiv = function () { this._endTag('div'); this._body.push('\n'); // make the generated HTML more human friendly return this; }; -HTMLBuilder.prototype.beginP = function(className, style, extraStyle) { +HTMLBuilder.prototype.beginP = function (className, style, extraStyle) { this._beginTag('p', className, style, extraStyle); this._body.push('\n'); // make the generated HTML more human friendly return this; }; -HTMLBuilder.prototype.endP = function() { +HTMLBuilder.prototype.endP = function () { this._flushText(); this._endTag('p'); this._body.push('\n'); // make the generated HTML more human friendly return this; }; -HTMLBuilder.prototype.beginSpan = function(className, style, extraStyle) { +HTMLBuilder.prototype.beginSpan = function (className, style, extraStyle) { this._flushText(); return this._beginTag('span', className, style, extraStyle); }; -HTMLBuilder.prototype.endSpan = function() { +HTMLBuilder.prototype.endSpan = function () { this._flushText(); return this._endTag('span'); }; -HTMLBuilder.prototype.putHTML = function(html) { +HTMLBuilder.prototype.putHTML = function (html) { this._flushText(); this._body.push(html); return this; }; -HTMLBuilder.prototype.putText = function(text) { +HTMLBuilder.prototype.putText = function (text) { this._textBuf.push(text); return this; }; -HTMLBuilder.prototype.write = function(html) { +HTMLBuilder.prototype.write = function (html) { this._body.push(html); }; -HTMLBuilder.prototype.toMarkup = function() { +HTMLBuilder.prototype.toMarkup = function () { this._flushText(); var html = this._body.join(''); return html.trim(); }; -HTMLBuilder.prototype.toDOM = function() { +HTMLBuilder.prototype.toDOM = function () { var html = this.toMarkup(); var div = document.createElement('div'); div.innerHTML = html; return div.firstChild; }; -HTMLBuilder.prototype._flushText = function() { +HTMLBuilder.prototype._flushText = function () { if (this._textBuf.length === 0) return; var text = this._textBuf.join(''); @@ -359,29 +354,31 @@ HTMLBuilder.prototype._flushText = function() { either a string, e.g., 'color:red', or an object, e.g. { color: 'red', margin-left: '1em'} */ -HTMLBuilder.prototype._beginTag = function(tag, className, style, extraStyle) { - var spanHTML = '<' + tag; - if (className) spanHTML += ' class="' + className + '"'; +HTMLBuilder.prototype._beginTag = function (tag, className, style, extraStyle) { + var spanHTML = `<${tag}`; + if (className) spanHTML += ` class="${className}"`; if (style) { var styleCode; - if (utils.isString(style)) styleCode = style; + if (utils.isString(style)) { + styleCode = style; + } else { // style styleCode = ''; for (var attrName in style) { attrVal = style[attrName]; - styleCode += attrName + ':' + attrVal + ';'; + styleCode += `${attrName}:${attrVal};`; } } if (extraStyle) styleCode += extraStyle; - spanHTML += ' style="' + styleCode + '"'; + spanHTML += ` style="${styleCode}"`; } spanHTML += '>'; this._body.push(spanHTML); return this; }; -HTMLBuilder.prototype._endTag = function(tag) { - this._body.push(''); +HTMLBuilder.prototype._endTag = function (tag) { + this._body.push(``); return this; }; @@ -394,10 +391,11 @@ var entityMap = { "/": '/', }; -HTMLBuilder.prototype._escapeHtml = function(string) { - return String(string).replace(/[&<>"'/]/g, function(s) { - return entityMap[s]; - }); +HTMLBuilder.prototype._escapeHtml = function (string) { + return String(string).replace( + /[&<>"'/]/g, + (s) => entityMap[s] + ); }; /* @@ -417,7 +415,7 @@ HTMLBuilder.prototype._escapeHtml = function(string) { * titlePrefix - The prefix in the title of the algorithm. Default value: 'Algorithm'. * **/ -function RendererOptions(options) { +function RendererOptions (options) { options = options || {}; this.indentSize = options.indentSize ? this._parseEmVal(options.indentSize) : 1.2; @@ -431,10 +429,11 @@ function RendererOptions(options) { this.titlePrefix = options.titlePrefix !== undefined ? options.titlePrefix : 'Algorithm'; } -RendererOptions.prototype._parseEmVal = function(emVal) { +RendererOptions.prototype._parseEmVal = function (emVal) { emVal = emVal.trim(); if (emVal.indexOf('em') !== emVal.length - 2) - throw 'option unit error; no `em` found'; + throw new TypeError('Unit error; expected `em` suffix'); + return Number(emVal.substring(0, emVal.length - 2)); }; @@ -444,7 +443,7 @@ RendererOptions.prototype._parseEmVal = function(emVal) { * There are three levels for renderer: Group (Block), Line and Segment, * which are rendered to HTML tag,
,

, and , respectively. **/ -function Renderer(parser, options) { +function Renderer (parser, options) { this._root = parser.parse(); this._options = new RendererOptions(options); this._openLine = false; @@ -482,32 +481,32 @@ function Renderer(parser, options) { /* The global counter for the numbering of the algorithm environment */ Renderer.captionCount = 0; -Renderer.prototype.toMarkup = function() { +Renderer.prototype.toMarkup = function () { var html = this._html = new HTMLBuilder(); this._buildTree(this._root); delete this._html; return html.toMarkup(); }; -Renderer.prototype.toDOM = function() { +Renderer.prototype.toDOM = function () { var html = this.toMarkup(); var div = document.createElement('div'); div.innerHTML = html; return div.firstChild; }; -Renderer.prototype._beginGroup = function(name, extraClass, style) { +Renderer.prototype._beginGroup = function (name, extraClass, style) { this._closeLineIfAny(); - this._html.beginDiv('ps-' + name + (extraClass ? ' ' + extraClass : ''), + this._html.beginDiv(`ps-${name}${extraClass ? ` ${extraClass}` : ''}`, style); }; -Renderer.prototype._endGroup = function(name) { +Renderer.prototype._endGroup = function (name) { this._closeLineIfAny(); this._html.endDiv(); }; -Renderer.prototype._beginBlock = function() { +Renderer.prototype._beginBlock = function () { // The first block have to extra left margin when line number are displayed var extraIndentForFirstBlock = this._options.lineNumber && this._blockLevel === 0 ? 0.6 : 0; @@ -519,18 +518,18 @@ Renderer.prototype._beginBlock = function() { blockIndent /= 2; this._beginGroup('block', null, { - 'margin-left': blockIndent + 'em', + 'margin-left': `${blockIndent}em`, }); this._blockLevel++; }; -Renderer.prototype._endBlock = function() { +Renderer.prototype._endBlock = function () { this._closeLineIfAny(); this._endGroup(); this._blockLevel--; }; -Renderer.prototype._newLine = function() { +Renderer.prototype._newLine = function () { this._closeLineIfAny(); this._openLine = true; @@ -554,7 +553,7 @@ Renderer.prototype._newLine = function() { if (this._options.lineNumber) { this._html .beginSpan('ps-linenum', { - 'left': -((this._blockLevel - 1) * (extraIndentSize)) + 'em', + 'left': `${-((this._blockLevel - 1) * (extraIndentSize))}em`, }) .putText(this._numLOC + this._options.lineNumberPunc) .endSpan(); @@ -563,13 +562,13 @@ Renderer.prototype._newLine = function() { // if this line is for pre-conditions (e.g. \REQUIRE) else { this._html.beginP('ps-line', { - 'text-indent': (-indentSize) + 'em', - 'padding-left': indentSize + 'em', + 'text-indent': `${-indentSize}em`, + 'padding-left': `${indentSize}em`, }, this._globalTextStyle.toCSS()); } }; -Renderer.prototype._closeLineIfAny = function() { +Renderer.prototype._closeLineIfAny = function () { if (!this._openLine) return; this._html.endP(); @@ -577,19 +576,19 @@ Renderer.prototype._closeLineIfAny = function() { this._openLine = false; }; -Renderer.prototype._typeKeyword = function(keyword) { +Renderer.prototype._typeKeyword = function (keyword) { this._html.beginSpan('ps-keyword').putText(keyword).endSpan(); }; -Renderer.prototype._typeFuncName = function(funcName) { +Renderer.prototype._typeFuncName = function (funcName) { this._html.beginSpan('ps-funcname').putText(funcName).endSpan(); }; -Renderer.prototype._typeText = function(text) { +Renderer.prototype._typeText = function (text) { this._html.write(text); }; -Renderer.prototype._buildTreeForAllChildren = function(node) { +Renderer.prototype._buildTreeForAllChildren = function (node) { var children = node.children; for (var ci = 0; ci < children.length; ci++) this._buildTree(children[ci]); @@ -597,7 +596,7 @@ Renderer.prototype._buildTreeForAllChildren = function(node) { // The comment nodes at the beginning of blockNode are comments for controls // Thus they should be rendered out of block -Renderer.prototype._buildCommentsFromBlock = function(blockNode) { +Renderer.prototype._buildCommentsFromBlock = function (blockNode) { var children = blockNode.children; while (children.length > 0 && children[0].type === 'comment') { var commentNode = children.shift(); @@ -605,7 +604,7 @@ Renderer.prototype._buildCommentsFromBlock = function(blockNode) { } }; -Renderer.prototype._buildTree = function(node) { +Renderer.prototype._buildTree = function (node) { var ci; var child; var textNode; switch (node.type) { // The hierarchicy of build tree: Group (Block) > Line > Text @@ -675,7 +674,7 @@ Renderer.prototype._buildTree = function(node) { textNode = node.children[0]; var blockNode = node.children[1]; this._newLine(); - this._typeKeyword(funcType + ' '); + this._typeKeyword(`${funcType} `); this._typeFuncName(defFuncName); this._typeText('('); this._buildTree(textNode); @@ -686,7 +685,7 @@ Renderer.prototype._buildTree = function(node) { if (!this._options.noEnd) { this._newLine(); - this._typeKeyword('end ' + funcType); + this._typeKeyword(`end ${funcType}`); } break; case 'if': @@ -767,7 +766,7 @@ Renderer.prototype._buildTree = function(node) { 'forall': 'for all', 'while': 'while', }; - this._typeKeyword(displayLoopName[loopType] + ' '); + this._typeKeyword(`${displayLoopName[loopType]} `); var loopCond = node.children[0]; this._buildTree(loopCond); this._typeKeyword(' do'); @@ -848,8 +847,8 @@ Renderer.prototype._buildTree = function(node) { break; case 'caption': this._newLine(); - this._typeKeyword(this._options.titlePrefix - + ' ' + Renderer.captionCount + ' '); + this._typeKeyword(`${this._options.titlePrefix + } ${Renderer.captionCount} `); textNode = node.children[0]; this._buildTree(textNode); break; @@ -891,7 +890,7 @@ Renderer.prototype._buildTree = function(node) { this._html.putHTML(closeTextEnv.renderToHTML(this.backend)); break; default: - throw new ParseError('Unexpected ParseNode of type ' + node.type); + throw new ParseError(`Unexpected ParseNode of type ${node.type}`); } }; diff --git a/src/utils.js b/src/utils.js index 6caa426..0e164ff 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,17 +1,19 @@ -function isString(str) { +function isString (str) { return (typeof str === 'string') || (str instanceof String); } -function isObject(obj) { +function isObject (obj) { return (typeof obj === 'object' && (obj instanceof Object)); } -function toString(obj) { - if (!isObject(obj)) return obj + ''; +function toString (obj) { + if (!isObject(obj)) + return `${obj}`; var parts = []; for (var member in obj) - parts.push(member + ': ' + toString(obj[member])); + parts.push(`${member}: ${toString(obj[member])}`); + return parts.join(', '); }