Bug fixes

This commit is contained in:
nicco 2018-02-09 15:00:58 +01:00
parent c16cc2f522
commit d90f695c9e
8 changed files with 94 additions and 123 deletions

View File

@ -1,10 +1,10 @@
import { compileBlock } from './compiler'
import { ActionFunction, re, error, options, Part } from './options'
import { ActionFunction, error, Part } from './options'
import { getFromObject, readFileSync } from './util'
import { join } from 'path'
import { computeParts } from './parser'
export const comment: ActionFunction = html => {
export const comment: ActionFunction = (html, options, re) => {
const tag = re.comment + re.ending
const end = html.indexOf(tag)
@ -17,7 +17,7 @@ export const comment: ActionFunction = html => {
}
}
export const logic: ActionFunction = html => {
export const logic: ActionFunction = (html, options, re) => {
const rexp = {
start: new RegExp(`${re.begin}\\${re.if} *\\${re.if_else}?${re.valid_variable} *${re.ending}`, 'g'),
@ -68,31 +68,31 @@ export const logic: ActionFunction = html => {
if (current.inverted) isTrue = !isTrue
if (isTrue)
return compileBlock(body.if).parts
return compileBlock(body.if, options, re).parts
else
return compileBlock(body.else).parts
return compileBlock(body.else, options, re).parts
}],
length: next.end.index + next.end[0].length
}
}
export const importer: ActionFunction = html => {
export const importer: ActionFunction = (html, options, re) => {
const end = html.indexOf(re.ending)
if (end === -1) throw new Error(error.parse.include_not_closed)
const template_name: string = html.substring(re.begin.length + re.incude.length, end).trim()
const file_name: string = join(options.template_dir, `${template_name}.${options.template_ext}`)
const file_name: string = join(options.views, `${template_name}.${options.extension}`)
const file: Part = readFileSync(file_name)
return {
parts: compileBlock(file).parts,
parts: compileBlock(file, options, re).parts,
length: end + re.ending.length
}
}
export const variables: ActionFunction = html => {
export const variables: ActionFunction = (html, options, re) => {
const end = html.indexOf(re.ending)
@ -114,7 +114,7 @@ export const variables: ActionFunction = html => {
}
}
export const loop: ActionFunction = html => {
export const loop: ActionFunction = (html, options, re) => {
const rexp = {
start: new RegExp(`${re.begin}\\${re.for} *${re.valid_variable} *${re.for_in} *${re.valid_variable} *${re.ending}`, 'g'),
@ -156,7 +156,7 @@ export const loop: ActionFunction = html => {
let ret = ''
for (const variable of getFromObject(data, current.arr)) {
const newData = Object.assign({ [current.variable]: variable }, data)
ret += computeParts(compileBlock(html).parts, newData)
ret += computeParts(compileBlock(html, options, re).parts, newData)
}
return ret
}],

View File

@ -1,55 +0,0 @@
import * as path from 'path'
import * as util from './util'
import * as parser from './parser'
import * as compiler from './compiler'
import { Compiled, options } from './options'
const cache: Map<string, Compiled> = new Map()
function compile(html: string): Compiled {
return {
template: compiler.process(html),
time: Date.now()
}
}
export function renderFile(file: string, data: any, callback: (err: any, render: string) => void): void {
util.readFile(file).then(html => {
util.checksum(html, true).then(hash => {
// Compile Template if is not in cache
if (options.caching && !cache.get(html))
cache.set(html, compile(html))
// Render the template and return the html
const compiled = cache.get(html)
if (compiled)
callback(null, parser.computeParts(compiled.template, data))
else
callback('Error: Chache not found', '')
})
})
}
export async function render(template_name: string, data?: any): Promise<string> {
const template_path = path.join(options.template_dir, `${template_name}.${options.template_ext}`)
// Compile Template if is not in cache
if (options.caching && !cache.get(template_name)) {
const html = await util.readFile(template_path)
if (html !== undefined)
cache.set(template_name, compile(html))
else {
'No file found'.log()
return ''
}
}
// Render the template and return the html
const compiled = cache.get(template_name)
if (compiled)
return parser.computeParts(compiled.template, data)
else
return ''
}
export const _express = renderFile

57
src/cometa.ts Normal file
View File

@ -0,0 +1,57 @@
import * as path from 'path'
import * as util from './util'
import * as parser from './parser'
import * as compiler from './compiler'
import { Compiled, options, Options, Expressions, re } from './options'
module.exports = class {
private cache: Map<string, Compiled>
private options: Options = options
private expressions: Expressions = re
constructor(opt?: Options, rexp?: Expressions) {
this.cache = new Map()
this.options = Object.assign(this.options, opt)
this.expressions = Object.assign(this.expressions, rexp)
if (module.parent === null)
throw new Error('Not imported')
this.options.views = path.join(path.dirname(module.parent.filename), this.options.views)
}
renderFile(file: string, data: any, callback: (err: any, render: string) => void): void {
console.log('Options', this.options)
util.readFile(file).then(html => {
console.log('Options', this.options)
if (html === undefined) {
callback(`No template found: ${file}`, '')
return
}
util.checksum(html, true).then(hash => {
// Compile Template if is not in cache
if (this.options.caching && !this.cache.get(html))
this.cache.set(html, {
template: compiler.process(html, this.options, this.expressions),
time: Date.now()
})
// Render the template and return the html
const compiled = this.cache.get(html)
if (compiled)
callback(null, parser.computeParts(compiled.template, data))
else
callback('Error: Chache not found', '')
})
})
}
renderTemplate(template_name: string, data: any, callback: (err: any, render: string) => void): void {
const template_path = path.join(this.options.views, `${template_name}.${this.options.extension}`)
this.renderFile(template_path, data, callback)
}
_express = this.renderFile
}

View File

@ -1,12 +1,13 @@
import { Part, re, error, ActionFunction, ActionReturn } from './options'
import { Part, error, ActionFunction, ActionReturn, options, Options, Expressions } from './options'
import * as actions from './actions'
const rexp = Object.freeze({
begin: new RegExp(re.begin, 'g'),
end: new RegExp(re.ending, 'g'),
})
export const compileBlock: ActionFunction = (part, optoins, re) => {
const rexp = Object.freeze({
begin: new RegExp(re.begin, 'g'),
end: new RegExp(re.ending, 'g'),
})
export const compileBlock: ActionFunction = part => {
interface Next {
start: number
end: number
@ -56,7 +57,7 @@ export const compileBlock: ActionFunction = part => {
break
}
const result = func(part)
const result = func(part, options, re)
addToRet(result.parts)
part = part.slice(result.length)
@ -68,8 +69,8 @@ export const compileBlock: ActionFunction = part => {
return ret
}
export function process(html: string, options = {}): Part[] {
const parts: Part[] = compileBlock(html).parts
export function process(html: string, options: Options, re: Expressions): Part[] {
const parts: Part[] = compileBlock(html, options, re).parts
return parts
}

View File

@ -17,7 +17,7 @@ export interface ActionReturn {
length: number
}
export type ActionFunction = (part: Render) => ActionReturn
export type ActionFunction = (part: Render, options: Options, re: Expressions) => ActionReturn
export interface Compiled {
template: Part[]
@ -36,27 +36,21 @@ export const error = {
}
interface Options {
export interface Options {
encoding: string
caching: boolean
template_dir: string
template_ext: string
compiled_dir: string
compiled_ext: string
max_recursion: number
views: string
extension: string
}
export const options: Options = {
encoding: 'utf-8',
caching: true,
template_dir: './views',
template_ext: 'html',
compiled_dir: './cache',
compiled_ext: 'bjs',
max_recursion: 100,
views: './views',
extension: 'html',
}
interface Expressions {
export interface Expressions {
begin: string
ending: string
comment: string

View File

@ -2,7 +2,7 @@ import { Part, Render, isRender, PartFunction } from "./options";
export function computeParts(parts: Part[], data = {}): Render {
if (parts.length === 0)
if (parts === undefined || parts.length === 0)
return ''
return computePart(parts[0], data) + computeParts(parts.slice(1), data)

View File

@ -1,21 +1,11 @@
import * as fs from 'fs'
import * as crypto from 'crypto'
declare global {
interface String {
log: () => void
}
}
String.prototype.log = function (): void {
console.log(this)
}
export function readFile(url: string): Promise<string> {
return new Promise(res => {
fs.readFile(url, (err, data) => {
if (err)
throw new Error(`No such file: ${url}`)
res()
else
res(data.toString())
})
@ -26,21 +16,6 @@ export function readFileSync(url: string): string {
return fs.readFileSync(url).toString()
}
export function writeFile(url: string, data: any): Promise<boolean> {
return new Promise(res => {
fs.writeFile(url, data, err => {
if (err)
res(false)
res(true)
})
})
}
export function writeFileSync(url: string, data: any): void {
fs.writeFileSync(url, data)
}
export function fileExists(url: string): Promise<boolean> {
return new Promise(res => {
fs.exists(url, _ => {
@ -57,6 +32,7 @@ export function checksum(url: string, plain = false, alg = 'sha1'): Promise<stri
res(hash.update(url).digest('hex'))
}
else {
// For large files
const stream = fs.createReadStream(url)
stream.on('data', data => hash.update(data, 'utf8'))
stream.on('end', _ => { res(hash.digest('hex')) })
@ -64,10 +40,6 @@ export function checksum(url: string, plain = false, alg = 'sha1'): Promise<stri
})
}
export function replaceBetween(start: number, end: number, str: string, replace: string): string {
return str.substring(0, start) + replace + str.substring(end)
}
export function getFromObject(data: any, name: string): any {
name = name.trim()
@ -79,9 +51,11 @@ export function getFromObject(data: any, name: string): any {
name = name.replace(/('|")/g, '')
name = name.replace(/\[(\w+)\]/g, '.$1')
for (const i of name.split('.'))
data = data[i]
try {
for (const i of name.split('.'))
data = data[i]
} catch (e) {
return ''
}
return data
}