diff --git a/deno_dist/README.md b/deno_dist/README.md index 7ee6e57..1c6d221 100644 --- a/deno_dist/README.md +++ b/deno_dist/README.md @@ -252,7 +252,7 @@ Made with ❤ by [@nebrelbug](https://github.com/eta-dev) and all these wonderfu
Ioan CHIRIAC

💻 🤔
Craig Morten

💻
Rajan Tiwari

💡 -
shadowtime2000

💻 🤔 +
shadowtime2000

💻 🤔 ⚠️
Hamza Hamidi

📖 diff --git a/deno_dist/compile-string.ts b/deno_dist/compile-string.ts index 797e5d9..5aa2674 100644 --- a/deno_dist/compile-string.ts +++ b/deno_dist/compile-string.ts @@ -22,9 +22,9 @@ export default function compileToString( str: string, config: EtaConfig, ): string { - var buffer: Array = Parse(str, config); + const buffer: Array = Parse(str, config); - var res = "var tR='',__l,__lP" + + let res = "var tR='',__l,__lP" + (config.include ? ",include=E.include.bind(E)" : "") + (config.includeFile ? ",includeFile=E.includeFile.bind(E)" : "") + "\nfunction layout(p,d){__l=p;__lP=d}\n" + @@ -43,8 +43,8 @@ export default function compileToString( (config.useWith ? "}" : ""); if (config.plugins) { - for (var i = 0; i < config.plugins.length; i++) { - var plugin = config.plugins[i]; + for (let i = 0; i < config.plugins.length; i++) { + const plugin = config.plugins[i]; if (plugin.processFnString) { res = plugin.processFnString(res, config); } @@ -68,20 +68,20 @@ export default function compileToString( */ function compileScope(buff: Array, config: EtaConfig) { - var i = 0; - var buffLength = buff.length; - var returnStr = ""; + let i = 0; + const buffLength = buff.length; + let returnStr = ""; for (i; i < buffLength; i++) { - var currentBlock = buff[i]; + const currentBlock = buff[i]; if (typeof currentBlock === "string") { - var str = currentBlock; + const str = currentBlock; // we know string exists returnStr += "tR+='" + str + "'\n"; } else { - var type = currentBlock.t; // ~, s, !, ?, r - var content = currentBlock.val || ""; + const type = currentBlock.t; // ~, s, !, ?, r + let content = currentBlock.val || ""; if (type === "r") { // raw diff --git a/deno_dist/compile.ts b/deno_dist/compile.ts index 32d4170..9bee022 100644 --- a/deno_dist/compile.ts +++ b/deno_dist/compile.ts @@ -35,17 +35,15 @@ export default function compile( str: string, config?: PartialConfig, ): TemplateFunction { - var options: EtaConfig = getConfig(config || {}); - var ctor; // constructor + const options: EtaConfig = getConfig(config || {}); /* ASYNC HANDLING */ // The below code is modified from mde/ejs. All credit should go to them. - if (options.async) { - ctor = getAsyncFunctionConstructor() as FunctionConstructor; - } else { - ctor = Function; - } + const ctor = options.async + ? (getAsyncFunctionConstructor() as FunctionConstructor) + : Function; /* END ASYNC HANDLING */ + try { return new ctor( options.varName, diff --git a/deno_dist/config.ts b/deno_dist/config.ts index 21a8296..a75cd64 100644 --- a/deno_dist/config.ts +++ b/deno_dist/config.ts @@ -110,7 +110,7 @@ function includeHelper( templateNameOrPath: string, data: object, ): string { - var template = this.templates.get(templateNameOrPath); + const template = this.templates.get(templateNameOrPath); if (!template) { throw EtaErr('Could not fetch template "' + templateNameOrPath + '"'); } @@ -118,7 +118,7 @@ function includeHelper( } /** Eta's base (global) configuration */ -var config: EtaConfig = { +const config: EtaConfig = { async: false, autoEscape: true, autoTrim: [false, "nl"], @@ -154,7 +154,7 @@ var config: EtaConfig = { function getConfig(override: PartialConfig, baseConfig?: EtaConfig): EtaConfig { // TODO: run more tests on this - var res: PartialConfig = {}; // Linked + const res: PartialConfig = {}; // Linked copyProps(res, config); // Creates deep clone of eta.config, 1 layer deep if (baseConfig) { diff --git a/deno_dist/containers.ts b/deno_dist/containers.ts index 004bcd2..51d6973 100644 --- a/deno_dist/containers.ts +++ b/deno_dist/containers.ts @@ -12,6 +12,6 @@ import type { TemplateFunction } from "./compile.ts"; * Stores partials and cached templates */ -var templates = new Cacher({}); +const templates = new Cacher({}); export { templates }; diff --git a/deno_dist/err.ts b/deno_dist/err.ts index 377228e..df2e42b 100644 --- a/deno_dist/err.ts +++ b/deno_dist/err.ts @@ -23,7 +23,7 @@ function setPrototypeOf(obj: any, proto: any) { */ export default function EtaErr(message: string): Error { - var err = new Error(message); + const err = new Error(message); setPrototypeOf(err, EtaErr.prototype); return err; } @@ -37,10 +37,10 @@ EtaErr.prototype = Object.create(Error.prototype, { */ export function ParseErr(message: string, str: string, indx: number): void { - var whitespace = str.slice(0, indx).split(/\n/); + const whitespace = str.slice(0, indx).split(/\n/); - var lineNo = whitespace.length; - var colNo = whitespace[lineNo - 1].length + 1; + const lineNo = whitespace.length; + const colNo = whitespace[lineNo - 1].length + 1; message += " at line " + lineNo + " col " + diff --git a/deno_dist/file-handlers.ts b/deno_dist/file-handlers.ts index 1fc50fe..543c0a8 100644 --- a/deno_dist/file-handlers.ts +++ b/deno_dist/file-handlers.ts @@ -45,10 +45,10 @@ export function loadFile( options: PartialConfigWithFilename, noCache?: boolean, ): TemplateFunction { - var config = getConfig(options); - var template = readFile(filePath); + const config = getConfig(options); + const template = readFile(filePath); try { - var compiledTemplate = compile(template, config); + const compiledTemplate = compile(template, config); if (!noCache) { config.templates.define( (config as EtaConfigWithFilename).filename, @@ -73,10 +73,10 @@ export function loadFile( */ function handleCache(options: EtaConfigWithFilename): TemplateFunction { - var filename = options.filename; + const filename = options.filename; if (options.cache) { - var func = options.templates.get(filename); + const func = options.templates.get(filename); if (func) { return func; } @@ -107,7 +107,7 @@ function tryHandleCache( try { // Note: if there is an error while rendering the template, // It will bubble up and be caught here - var templateFn = handleCache(options); + const templateFn = handleCache(options); templateFn(data, options, cb); } catch (err) { return cb(err); @@ -118,8 +118,8 @@ function tryHandleCache( return new promiseImpl( function (resolve: Function, reject: Function) { try { - var templateFn = handleCache(options); - var result = templateFn(data, options); + const templateFn = handleCache(options); + const result = templateFn(data, options); resolve(result); } catch (err) { reject(err); @@ -156,7 +156,10 @@ function includeFile( options: EtaConfig, ): [TemplateFunction, EtaConfig] { // the below creates a new options object, using the parent filepath of the old options object and the path - var newFileOptions = getConfig({ filename: getPath(path, options) }, options); + const newFileOptions = getConfig( + { filename: getPath(path, options) }, + options, + ); // TODO: make sure properties are currectly copied over return [handleCache(newFileOptions as EtaConfigWithFilename), newFileOptions]; } @@ -215,8 +218,8 @@ function renderFile( And we want to also make (filename, data, options, cb) available */ - var renderConfig: EtaConfigWithFilename; - var callback: CallbackFn | undefined; + let renderConfig: EtaConfigWithFilename; + let callback: CallbackFn | undefined; data = data || {}; // If data is undefined, we don't want accessing data.settings to error // First, assign our callback function to `callback` @@ -250,7 +253,7 @@ function renderFile( } // Undocumented after Express 2, but still usable, esp. for // items that are unsafe to be passed along with data, like `root` - var viewOpts = data.settings["view options"]; + const viewOpts = data.settings["view options"]; if (viewOpts) { copyProps(renderConfig, viewOpts); @@ -284,7 +287,12 @@ function renderFileAsync( config?: PartialConfig, cb?: CallbackFn, ): Promise | void { - return renderFile(filename, data, { ...config, async: true }, cb); + return renderFile( + filename, + typeof config === "function" ? { ...data, async: true } : data, + typeof config === "object" ? { ...config, async: true } : config, + cb, + ); } export { includeFile, renderFile, renderFileAsync }; diff --git a/deno_dist/file-helpers.ts b/deno_dist/file-helpers.ts index a009c40..5c5f984 100644 --- a/deno_dist/file-helpers.ts +++ b/deno_dist/file-helpers.ts @@ -19,6 +19,6 @@ export function includeFileHelper( path: string, data: GenericData, ): string { - var templateAndConfig = includeFile(path, this); + const templateAndConfig = includeFile(path, this); return templateAndConfig[0](data, templateAndConfig[1]); } diff --git a/deno_dist/file-methods.ts b/deno_dist/file-methods.ts index b4c921f..8e9ffa8 100644 --- a/deno_dist/file-methods.ts +++ b/deno_dist/file-methods.ts @@ -1,4 +1,4 @@ export * as fs from "https://deno.land/std@0.66.0/fs/mod.ts"; export * as path from "https://deno.land/std@0.66.0/path/mod.ts"; -export var readFileSync = Deno.readTextFileSync; +export const readFileSync = Deno.readTextFileSync; diff --git a/deno_dist/file-utils.ts b/deno_dist/file-utils.ts index eca8080..0818cfe 100644 --- a/deno_dist/file-utils.ts +++ b/deno_dist/file-utils.ts @@ -1,5 +1,5 @@ import { fs, path, readFileSync } from "./file-methods.ts"; -var _BOM = /^\uFEFF/; +const _BOM = /^\uFEFF/; // express is set like: app.engine('html', require('eta').renderFile) @@ -28,14 +28,10 @@ function getWholeFilePath( parentfile: string, isDirectory?: boolean, ): string { - var includePath = path.resolve( + const includePath = path.resolve( isDirectory ? parentfile : path.dirname(parentfile), // returns directory the parent file is in name, // file - ); - var ext = path.extname(name); - if (!ext) { - includePath += ".eta"; - } + ) + (path.extname(name) ? "" : ".eta"); return includePath; } @@ -58,15 +54,15 @@ function getWholeFilePath( */ function getPath(path: string, options: EtaConfig): string { - var includePath: string | false = false; - var views = options.views; - var searchedPaths: Array = []; + let includePath: string | false = false; + const views = options.views; + let searchedPaths: Array = []; // If these four values are the same, // getPath() will return the same result every time. // We can cache the result to avoid expensive // file operations. - var pathOptions = JSON.stringify({ + const pathOptions = JSON.stringify({ filename: options.filename, // filename of the template which called includeFile() path: path, root: options.root, @@ -99,7 +95,7 @@ function getPath(path: string, options: EtaConfig): string { views: Array | string | undefined, path: string, ): string | false { - var filePath; + let filePath; // If views is an array, then loop through each directory // And attempt to find the template @@ -132,20 +128,20 @@ function getPath(path: string, options: EtaConfig): string { } // Path starts with '/', 'C:\', etc. - var match = /^[A-Za-z]+:\\|^\//.exec(path); + const match = /^[A-Za-z]+:\\|^\//.exec(path); // Absolute path, like /partials/partial.eta if (match && match.length) { // We have to trim the beginning '/' off the path, or else // path.resolve(dir, path) will always resolve to just path - var formattedPath = path.replace(/^\/*/, ""); + const formattedPath = path.replace(/^\/*/, ""); // First, try to resolve the path within options.views includePath = searchViews(views, formattedPath); if (!includePath) { // If that fails, searchViews will return false. Try to find the path // inside options.root (by default '/', the base of the filesystem) - var pathFromRoot = getWholeFilePath( + const pathFromRoot = getWholeFilePath( formattedPath, options.root || "/", true, @@ -159,7 +155,7 @@ function getPath(path: string, options: EtaConfig): string { // Relative paths // Look relative to a passed filename first if (options.filename) { - var filePath = getWholeFilePath(path, options.filename); + const filePath = getWholeFilePath(path, options.filename); addPathToSearched(filePath); diff --git a/deno_dist/parse.ts b/deno_dist/parse.ts index 19e69fc..442630c 100644 --- a/deno_dist/parse.ts +++ b/deno_dist/parse.ts @@ -16,12 +16,12 @@ export type AstObject = string | TemplateObject; /* END TYPES */ -var templateLitReg = +const templateLitReg = /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})*}|(?!\${)[^\\`])*`/g; -var singleQuoteReg = /'(?:\\[\s\w"'\\`]|[^\n\r'\\])*?'/g; +const singleQuoteReg = /'(?:\\[\s\w"'\\`]|[^\n\r'\\])*?'/g; -var doubleQuoteReg = /"(?:\\[\s\w"'\\`]|[^\n\r"\\])*?"/g; +const doubleQuoteReg = /"(?:\\[\s\w"'\\`]|[^\n\r"\\])*?"/g; /** Escape special regular expression characters inside a string */ @@ -34,14 +34,14 @@ export default function parse( str: string, config: EtaConfig, ): Array { - var buffer: Array = []; - var trimLeftOfNextStr: string | false = false; - var lastIndex = 0; - var parseOptions = config.parse; + let buffer: Array = []; + let trimLeftOfNextStr: string | false = false; + let lastIndex = 0; + const parseOptions = config.parse; if (config.plugins) { - for (var i = 0; i < config.plugins.length; i++) { - var plugin = config.plugins[i]; + for (let i = 0; i < config.plugins.length; i++) { + const plugin = config.plugins[i]; if (plugin.processTemplate) { str = plugin.processTemplate(str, config); } @@ -85,72 +85,74 @@ export default function parse( } } - var prefixes = [parseOptions.exec, parseOptions.interpolate, parseOptions.raw] - .reduce(function ( - accumulator, - prefix, - ) { - if (accumulator && prefix) { - return accumulator + "|" + escapeRegExp(prefix); - } else if (prefix) { - // accumulator is falsy - return escapeRegExp(prefix); - } else { - // prefix and accumulator are both falsy - return accumulator; - } - }, ""); + const prefixes = [ + parseOptions.exec, + parseOptions.interpolate, + parseOptions.raw, + ].reduce(function ( + accumulator, + prefix, + ) { + if (accumulator && prefix) { + return accumulator + "|" + escapeRegExp(prefix); + } else if (prefix) { + // accumulator is falsy + return escapeRegExp(prefix); + } else { + // prefix and accumulator are both falsy + return accumulator; + } + }, ""); - var parseOpenReg = new RegExp( + const parseOpenReg = new RegExp( "([^]*?)" + escapeRegExp(config.tags[0]) + "(-|_)?\\s*(" + prefixes + ")?\\s*", "g", ); - var parseCloseReg = new RegExp( + const parseCloseReg = new RegExp( "'|\"|`|\\/\\*|(\\s*(-|_)?" + escapeRegExp(config.tags[1]) + ")", "g", ); // TODO: benchmark having the \s* on either side vs using str.trim() - var m; + let m; while ((m = parseOpenReg.exec(str))) { lastIndex = m[0].length + m.index; - var precedingString = m[1]; - var wsLeft = m[2]; - var prefix = m[3] || ""; // by default either ~, =, or empty + const precedingString = m[1]; + const wsLeft = m[2]; + const prefix = m[3] || ""; // by default either ~, =, or empty pushString(precedingString, wsLeft); parseCloseReg.lastIndex = lastIndex; - var closeTag; - var currentObj: AstObject | false = false; + let closeTag; + let currentObj: AstObject | false = false; while ((closeTag = parseCloseReg.exec(str))) { if (closeTag[1]) { - var content = str.slice(lastIndex, closeTag.index); + let content = str.slice(lastIndex, closeTag.index); parseOpenReg.lastIndex = lastIndex = parseCloseReg.lastIndex; trimLeftOfNextStr = closeTag[2]; - var currentType: TagType = ""; - if (prefix === parseOptions.exec) { - currentType = "e"; - } else if (prefix === parseOptions.raw) { - currentType = "r"; - } else if (prefix === parseOptions.interpolate) { - currentType = "i"; - } + const currentType: TagType = prefix === parseOptions.exec + ? "e" + : prefix === parseOptions.raw + ? "r" + : prefix === parseOptions.interpolate + ? "i" + : ""; currentObj = { t: currentType, val: content }; break; } else { - var char = closeTag[0]; + const char = closeTag[0]; if (char === "/*") { - var commentCloseInd = str.indexOf("*/", parseCloseReg.lastIndex); + const commentCloseInd = str.indexOf("*/", parseCloseReg.lastIndex); if (commentCloseInd === -1) { ParseErr("unclosed comment", str, closeTag.index); @@ -159,7 +161,7 @@ export default function parse( } else if (char === "'") { singleQuoteReg.lastIndex = closeTag.index; - var singleQuoteMatch = singleQuoteReg.exec(str); + const singleQuoteMatch = singleQuoteReg.exec(str); if (singleQuoteMatch) { parseCloseReg.lastIndex = singleQuoteReg.lastIndex; } else { @@ -167,7 +169,7 @@ export default function parse( } } else if (char === '"') { doubleQuoteReg.lastIndex = closeTag.index; - var doubleQuoteMatch = doubleQuoteReg.exec(str); + const doubleQuoteMatch = doubleQuoteReg.exec(str); if (doubleQuoteMatch) { parseCloseReg.lastIndex = doubleQuoteReg.lastIndex; @@ -176,7 +178,7 @@ export default function parse( } } else if (char === "`") { templateLitReg.lastIndex = closeTag.index; - var templateLitMatch = templateLitReg.exec(str); + const templateLitMatch = templateLitReg.exec(str); if (templateLitMatch) { parseCloseReg.lastIndex = templateLitReg.lastIndex; } else { @@ -195,8 +197,8 @@ export default function parse( pushString(str.slice(lastIndex, str.length), false); if (config.plugins) { - for (var i = 0; i < config.plugins.length; i++) { - var plugin = config.plugins[i]; + for (let i = 0; i < config.plugins.length; i++) { + const plugin = config.plugins[i]; if (plugin.processAST) { buffer = plugin.processAST(buffer, config); } diff --git a/deno_dist/polyfills.ts b/deno_dist/polyfills.ts index b0b60a5..2d60c0a 100644 --- a/deno_dist/polyfills.ts +++ b/deno_dist/polyfills.ts @@ -1,4 +1,4 @@ -export var promiseImpl = Promise; +export const promiseImpl = Promise; export function getAsyncFunctionConstructor(): Function { return async function () {}.constructor; diff --git a/deno_dist/render.ts b/deno_dist/render.ts index 2605606..8b71c38 100644 --- a/deno_dist/render.ts +++ b/deno_dist/render.ts @@ -15,17 +15,13 @@ function handleCache( template: string | TemplateFunction, options: EtaConfig, ): TemplateFunction { - var templateFunc; - if (options.cache && options.name && options.templates.get(options.name)) { return options.templates.get(options.name); } - if (typeof template === "function") { - templateFunc = template; - } else { - templateFunc = compile(template, options); - } + const templateFunc = typeof template === "function" + ? template + : compile(template, options); // Note that we don't have to check if it already exists in the cache; // it would have returned earlier if it had @@ -61,16 +57,15 @@ export default function render( config?: PartialConfig, cb?: CallbackFn, ): string | Promise | void { - var options = getConfig(config || {}); + const options = getConfig(config || {}); if (options.async) { - var result; if (cb) { // If user passes callback try { // Note: if there is an error while rendering the template, // It will bubble up and be caught here - var templateFn = handleCache(template, options); + const templateFn = handleCache(template, options); templateFn(data, options, cb); } catch (err) { return cb(err); @@ -80,8 +75,7 @@ export default function render( if (typeof promiseImpl === "function") { return new promiseImpl(function (resolve: Function, reject: Function) { try { - result = handleCache(template, options)(data, options); - resolve(result); + resolve(handleCache(template, options)(data, options)); } catch (err) { reject(err); } @@ -103,6 +97,6 @@ export function renderAsync( config?: PartialConfig, cb?: CallbackFn, ): string | Promise | void { - // Using Object.assign to lower bundle size, using spread operator makes it larger + // Using Object.assign to lower bundle size, using spread operator makes it larger because of typescript injected polyfills return render(template, data, Object.assign({}, config, { async: true }), cb); } diff --git a/deno_dist/utils.ts b/deno_dist/utils.ts index a773363..9e08b43 100644 --- a/deno_dist/utils.ts +++ b/deno_dist/utils.ts @@ -23,7 +23,7 @@ export function hasOwnProp(obj: object, prop: string): boolean { } export function copyProps(toObj: T, fromObj: T): T { - for (var key in fromObj) { + for (const key in fromObj) { if (hasOwnProp((fromObj as unknown) as object, key)) { toObj[key] = fromObj[key]; } @@ -41,8 +41,8 @@ function trimWS( wsLeft: string | false, wsRight?: string | false, ): string { - var leftTrim; - var rightTrim; + let leftTrim; + let rightTrim; if (Array.isArray(config.autoTrim)) { // kinda confusing @@ -94,7 +94,7 @@ function trimWS( * A map of special HTML characters to their XML-escaped equivalents */ -var escMap: EscapeMap = { +const escMap: EscapeMap = { "&": "&", "<": "<", ">": ">", @@ -116,7 +116,7 @@ function replaceChar(s: string): string { function XMLEscape(str: any): string { // eslint-disable-line @typescript-eslint/no-explicit-any // To deal with XSS. Based on Escape implementations of Mustache.JS and Marko, then customized. - var newStr = String(str); + const newStr = String(str); if (/[&<>"']/.test(newStr)) { return newStr.replace(/[&<>"']/g, replaceChar); } else { diff --git a/src/file-handlers.ts b/src/file-handlers.ts index 08b13cd..a341bf9 100644 --- a/src/file-handlers.ts +++ b/src/file-handlers.ts @@ -256,7 +256,12 @@ function renderFileAsync( config?: PartialConfig, cb?: CallbackFn ): Promise | void { - return renderFile(filename, data, { ...config, async: true }, cb) + return renderFile( + filename, + typeof config === 'function' ? { ...data, async: true } : data, + typeof config === 'object' ? { ...config, async: true } : config, + cb + ) } export { includeFile, renderFile, renderFileAsync } diff --git a/src/file-utils.ts b/src/file-utils.ts index 3a47e76..5c942e2 100644 --- a/src/file-utils.ts +++ b/src/file-utils.ts @@ -24,10 +24,11 @@ import type { EtaConfig } from './config' */ function getWholeFilePath(name: string, parentfile: string, isDirectory?: boolean): string { - const includePath = path.resolve( - isDirectory ? parentfile : path.dirname(parentfile), // returns directory the parent file is in - name // file - ) + (path.extname(name) ? '' : '.eta') + const includePath = + path.resolve( + isDirectory ? parentfile : path.dirname(parentfile), // returns directory the parent file is in + name // file + ) + (path.extname(name) ? '' : '.eta') return includePath } diff --git a/src/render.ts b/src/render.ts index 5a4e310..0e53a1a 100644 --- a/src/render.ts +++ b/src/render.ts @@ -90,6 +90,6 @@ export function renderAsync( config?: PartialConfig, cb?: CallbackFn ): string | Promise | void { - // Using Object.assign to lower bundle size, using spread operator makes it larger + // Using Object.assign to lower bundle size, using spread operator makes it larger because of typescript injected polyfills return render(template, data, Object.assign({}, config, { async: true }), cb) }