master
宇天 2020-09-27 19:32:13 +08:00
parent c9b33e6cbc
commit cb26c1b2f7
6 changed files with 116 additions and 90 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@
node_modules/ node_modules/
cache/

View File

@ -14,17 +14,26 @@ function hash(str) {
return Buffer.from(str).toString('hex') return Buffer.from(str).toString('hex')
} }
var cacheDir = path.resolve(__dirname, './cache/')
class Smarty { class Smarty {
constructor(opt) { constructor(opt) {
this.opt = { cache: true, ext: '.htm' } this.opt = { ext: '.htm' }
if (opt) { if (opt) {
Object.assign(this.opt, opt) Object.assign(this.opt, opt)
} }
this.__REG__ = new RegExp(this.opt.ext + '$') this.__REG__ = new RegExp(this.opt.ext + '$')
this.tool = new Tool(this.opt) this.tool = new Tool(this.opt)
this.__DATA__ = Object.create(null) // 预定义的变量储存
this.reset()
this.__CACHE__ = Object.create(null) // 渲染缓存 this.__CACHE__ = Object.create(null) // 渲染缓存
// 消除缓存目录
fs.rm(cacheDir)
}
reset() {
this.__DATA__ = Object.create(null) // 预定义的变量储存
} }
config(key, val) { config(key, val) {
@ -53,46 +62,53 @@ class Smarty {
/** /**
* [render 模板渲染] * [render 模板渲染]
* @param {String} tpl 模板路径 * @param {String} filePath 模板路径
* @param {Boolean} noParse 不解析直接读取 * @param {Boolean} noParse 不解析直接读取
* @return {Promise} 返回一个Promise对象 * @return {Promise} 返回一个Promise对象
*/ */
render(tpl = '', noParse = false) { render(filePath = '', noParse = false) {
var key = null var key, ckey, cache, needWrite
var cache
if (!this.opt.path) { if (!this.opt.path) {
throw new Error('Smarty engine must define path option') throw new Error('Smarty engine must define path option')
} }
if (!tpl) { if (!filePath) {
return Promise.reject('argument[tpl] can not be empty') return Promise.reject('argument[filePath] can not be empty')
} }
if (!this.__REG__.test(tpl)) { if (!this.__REG__.test(filePath)) {
tpl += this.opt.ext filePath += this.opt.ext
} }
tpl = path.resolve(this.opt.path, tpl) filePath = path.resolve(this.opt.path, filePath)
key = hash(tpl) key = hash(filePath)
ckey = path.join(cacheDir, key)
if (this.__CACHE__[key]) { if (this.__CACHE__[key]) {
return Promise.resolve(fs.cat(path.resolve('./cache/', key))) cache = fs.cat(ckey)
} else {
cache = fs.cat(filePath)
this.__CACHE__[key] = true
needWrite = true
} }
cache = this.tool.__readFile__(tpl, noParse) // 无需解析时, 直接输出
if (noParse) { if (noParse) {
this.__CACHE__[key] = true if (needWrite) {
fs.echo(cache, path.resolve('./cache/', key)) fs.echo(cache, ckey)
}
return Promise.resolve(cache) return Promise.resolve(cache)
} else {
if (needWrite) {
cache = this.tool.parse(cache)
fs.echo(cache, ckey)
}
} }
try { try {
cache = this.tool.parse(cache, this.__DATA__) var body = this.tool.exec(cache, this.__DATA__)
if (this.opt.cache) { this.reset()
this.__CACHE__[key] = true return Promise.resolve(body)
fs.echo(cache, path.resolve('./cache/', key))
}
return Promise.resolve(cache)
} catch (err) { } catch (err) {
return Promise.reject(err) return Promise.reject(err)
} }

View File

@ -7,6 +7,7 @@
import 'es.shim' import 'es.shim'
import path from 'path' import path from 'path'
import fs from 'iofs' import fs from 'iofs'
import { fileURLToPath } from 'url'
import Tool from './lib/tool.mjs' import Tool from './lib/tool.mjs'
@ -14,17 +15,27 @@ function hash(str) {
return Buffer.from(str).toString('hex') return Buffer.from(str).toString('hex')
} }
var __dirname = path.dirname(fileURLToPath(import.meta.url))
var cacheDir = path.resolve(__dirname, './cache/')
export default class Smarty { export default class Smarty {
constructor(opt) { constructor(opt) {
this.opt = { cache: true, ext: '.htm' } this.opt = { ext: '.htm' }
if (opt) { if (opt) {
Object.assign(this.opt, opt) Object.assign(this.opt, opt)
} }
this.__REG__ = new RegExp(this.opt.ext + '$') this.__REG__ = new RegExp(this.opt.ext + '$')
this.tool = new Tool(this.opt) this.tool = new Tool(this.opt)
this.__DATA__ = Object.create(null) // 预定义的变量储存
this.reset()
this.__CACHE__ = Object.create(null) // 渲染缓存 this.__CACHE__ = Object.create(null) // 渲染缓存
// 消除缓存目录
fs.rm(cacheDir)
}
reset() {
this.__DATA__ = Object.create(null) // 预定义的变量储存
} }
config(key, val) { config(key, val) {
@ -58,8 +69,8 @@ export default class Smarty {
* @return {Promise} 返回一个Promise对象 * @return {Promise} 返回一个Promise对象
*/ */
render(filePath = '', noParse = false) { render(filePath = '', noParse = false) {
var key = null var key, ckey, cache, needWrite
var cache
if (!this.opt.path) { if (!this.opt.path) {
throw new Error('Smarty engine must define path option') throw new Error('Smarty engine must define path option')
} }
@ -73,26 +84,33 @@ export default class Smarty {
filePath = path.resolve(this.opt.path, filePath) filePath = path.resolve(this.opt.path, filePath)
key = hash(filePath) key = hash(filePath)
ckey = path.join(cacheDir, key)
if (this.__CACHE__[key]) { if (this.__CACHE__[key]) {
return Promise.resolve(fs.cat(path.resolve('./cache/', key))) cache = fs.cat(ckey)
} else {
cache = fs.cat(filePath)
this.__CACHE__[key] = true
needWrite = true
} }
cache = this.tool.__readFile__(filePath, noParse) // 无需解析时, 直接输出
if (noParse) { if (noParse) {
this.__CACHE__[key] = true if (needWrite) {
fs.echo(cache, path.resolve('./cache/', key)) fs.echo(cache, ckey)
}
return Promise.resolve(cache) return Promise.resolve(cache)
} else {
if (needWrite) {
cache = this.tool.parse(cache)
fs.echo(cache, ckey)
}
} }
try { try {
cache = this.tool.parse(cache, this.__DATA__) var body = this.tool.exec(cache, this.__DATA__)
if (this.opt.cache) { this.reset()
this.__CACHE__[key] = true return Promise.resolve(body)
fs.echo(cache, path.resolve('./cache/', key))
}
return Promise.resolve(cache)
} catch (err) { } catch (err) {
return Promise.reject(err) return Promise.reject(err)
} }

View File

@ -69,21 +69,20 @@ class Tool {
} }
} }
__readFile__(file, noParse) { __readFile__(file) {
var buf = null
if (!fs.exists(file)) { if (!fs.exists(file)) {
throw new Error(`Can not find template "${file}"`) throw new Error(`Can not find template "${file}"`)
} }
buf = fs.cat(file).toString() return this.__fixed__(fs.cat(file).toString())
if (noParse) {
return buf
} }
return buf __fixed__(str) {
return str
.trim()
.replace(/[\r\n\t]+/g, ' ') // 去掉所有的换行/制表 .replace(/[\r\n\t]+/g, ' ') // 去掉所有的换行/制表
.replace(/\\/g, '\\\\') .replace(/\\/g, '\\\\')
.replace(/`/g, '\\`')
} }
//生成正则 //生成正则
@ -312,24 +311,24 @@ class Tool {
} }
//解析模板 //解析模板
parse(str, data) { parse(buf) {
var str = this.__fixed__(buf.toString())
str = this.parseExtends(str)
str = this.parseNormal(str)
return str
}
exec(str, data) {
var vars = `"use strict"; let __filters__ = f; ` var vars = `"use strict"; let __filters__ = f; `
var body = ''
for (let i in data) { for (let i in data) {
let tmp = JSON.stringify(data[i]) || '' let tmp = JSON.stringify(data[i]) || ''
vars += `let ${i} = ${tmp}; ` vars += `let ${i} = ${tmp}; `
} }
str = str
.trim()
.replace(/[\r\n\t]+/g, ' ') // 去掉所有的换行/制表
.replace(/\\/g, '\\\\')
.replace(/`/g, '\\`')
str = this.parseExtends(str) body = `${vars} let tpl=\`${str}\`; return tpl;`
str = this.parseNormal(str)
str = `${vars} let tpl=\`${str}\`; return tpl;` return new Function('f', body)(this.filters)
return new Function('f', str)(this.filters)
} }
} }

View File

@ -69,21 +69,20 @@ export default class Tool {
} }
} }
__readFile__(file, noParse) { __readFile__(file) {
var buf = null
if (!fs.exists(file)) { if (!fs.exists(file)) {
throw new Error(`Can not find template "${file}"`) throw new Error(`Can not find template "${file}"`)
} }
buf = fs.cat(file).toString() return this.__fixed__(fs.cat(file).toString())
if (noParse) {
return buf
} }
return buf __fixed__(str) {
return str
.trim()
.replace(/[\r\n\t]+/g, ' ') // 去掉所有的换行/制表 .replace(/[\r\n\t]+/g, ' ') // 去掉所有的换行/制表
.replace(/\\/g, '\\\\') .replace(/\\/g, '\\\\')
.replace(/`/g, '\\`')
} }
//生成正则 //生成正则
@ -312,23 +311,23 @@ export default class Tool {
} }
//解析模板 //解析模板
parse(str, data) { parse(buf) {
var str = this.__fixed__(buf.toString())
str = this.parseExtends(str)
str = this.parseNormal(str)
return str
}
exec(str, data) {
var vars = `"use strict"; let __filters__ = f; ` var vars = `"use strict"; let __filters__ = f; `
var body = ''
for (let i in data) { for (let i in data) {
let tmp = JSON.stringify(data[i]) || '' let tmp = JSON.stringify(data[i]) || ''
vars += `let ${i} = ${tmp}; ` vars += `let ${i} = ${tmp}; `
} }
str = str
.trim()
.replace(/[\r\n\t]+/g, ' ') // 去掉所有的换行/制表
.replace(/\\/g, '\\\\')
.replace(/`/g, '\\`')
str = this.parseExtends(str) body = `${vars} let tpl=\`${str}\`; return tpl;`
str = this.parseNormal(str)
str = `${vars} let tpl=\`${str}\`; return tpl;` return new Function('f', body)(this.filters)
return new Function('f', str)(this.filters)
} }
} }

View File

@ -1,23 +1,16 @@
{ {
"name": "smartyx", "name": "smartyx",
"version": "2.0.1", "version": "2.1.0",
"description": "nodeJS模板引擎理念源自于PHP的smarty模板引擎", "description": "nodeJS模板引擎理念源自于PHP的smarty模板引擎",
"keywords": [ "keywords": ["fivejs", "php", "smarty", "template", "ejs", "jade"],
"fivejs",
"php",
"smarty",
"template",
"ejs",
"jade"
],
"author": "yutent <yutent.io@gmail.com>", "author": "yutent <yutent.io@gmail.com>",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/bytedo/smarty.git" "url": "https://github.com/bytedo/smarty.git"
}, },
"dependencies": { "dependencies": {
"es.shim": "^2.0.0", "es.shim": "^2.0.1",
"iofs": "^1.4.0" "iofs": "^1.5.0"
}, },
"main": "index.js", "main": "index.js",
"exports": { "exports": {