mirror of
https://github.com/cupcakearmy/cometa.git
synced 2025-03-12 14:27:28 +00:00
Bug fixes
This commit is contained in:
parent
c16cc2f522
commit
d90f695c9e
@ -1,10 +1,10 @@
|
|||||||
import { compileBlock } from './compiler'
|
import { compileBlock } from './compiler'
|
||||||
import { ActionFunction, re, error, options, Part } from './options'
|
import { ActionFunction, error, Part } from './options'
|
||||||
import { getFromObject, readFileSync } from './util'
|
import { getFromObject, readFileSync } from './util'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { computeParts } from './parser'
|
import { computeParts } from './parser'
|
||||||
|
|
||||||
export const comment: ActionFunction = html => {
|
export const comment: ActionFunction = (html, options, re) => {
|
||||||
|
|
||||||
const tag = re.comment + re.ending
|
const tag = re.comment + re.ending
|
||||||
const end = html.indexOf(tag)
|
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 = {
|
const rexp = {
|
||||||
start: new RegExp(`${re.begin}\\${re.if} *\\${re.if_else}?${re.valid_variable} *${re.ending}`, 'g'),
|
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 (current.inverted) isTrue = !isTrue
|
||||||
|
|
||||||
if (isTrue)
|
if (isTrue)
|
||||||
return compileBlock(body.if).parts
|
return compileBlock(body.if, options, re).parts
|
||||||
else
|
else
|
||||||
return compileBlock(body.else).parts
|
return compileBlock(body.else, options, re).parts
|
||||||
}],
|
}],
|
||||||
length: next.end.index + next.end[0].length
|
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)
|
const end = html.indexOf(re.ending)
|
||||||
|
|
||||||
if (end === -1) throw new Error(error.parse.include_not_closed)
|
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 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)
|
const file: Part = readFileSync(file_name)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
parts: compileBlock(file).parts,
|
parts: compileBlock(file, options, re).parts,
|
||||||
length: end + re.ending.length
|
length: end + re.ending.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const variables: ActionFunction = html => {
|
export const variables: ActionFunction = (html, options, re) => {
|
||||||
|
|
||||||
const end = html.indexOf(re.ending)
|
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 = {
|
const rexp = {
|
||||||
start: new RegExp(`${re.begin}\\${re.for} *${re.valid_variable} *${re.for_in} *${re.valid_variable} *${re.ending}`, 'g'),
|
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 = ''
|
let ret = ''
|
||||||
for (const variable of getFromObject(data, current.arr)) {
|
for (const variable of getFromObject(data, current.arr)) {
|
||||||
const newData = Object.assign({ [current.variable]: variable }, data)
|
const newData = Object.assign({ [current.variable]: variable }, data)
|
||||||
ret += computeParts(compileBlock(html).parts, newData)
|
ret += computeParts(compileBlock(html, options, re).parts, newData)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}],
|
}],
|
||||||
|
55
src/blitz.ts
55
src/blitz.ts
@ -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
57
src/cometa.ts
Normal 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
|
||||||
|
|
||||||
|
}
|
@ -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'
|
import * as actions from './actions'
|
||||||
|
|
||||||
const rexp = Object.freeze({
|
export const compileBlock: ActionFunction = (part, optoins, re) => {
|
||||||
begin: new RegExp(re.begin, 'g'),
|
|
||||||
end: new RegExp(re.ending, 'g'),
|
const rexp = Object.freeze({
|
||||||
})
|
begin: new RegExp(re.begin, 'g'),
|
||||||
|
end: new RegExp(re.ending, 'g'),
|
||||||
|
})
|
||||||
|
|
||||||
export const compileBlock: ActionFunction = part => {
|
|
||||||
interface Next {
|
interface Next {
|
||||||
start: number
|
start: number
|
||||||
end: number
|
end: number
|
||||||
@ -56,7 +57,7 @@ export const compileBlock: ActionFunction = part => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = func(part)
|
const result = func(part, options, re)
|
||||||
addToRet(result.parts)
|
addToRet(result.parts)
|
||||||
part = part.slice(result.length)
|
part = part.slice(result.length)
|
||||||
|
|
||||||
@ -68,8 +69,8 @@ export const compileBlock: ActionFunction = part => {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
export function process(html: string, options = {}): Part[] {
|
export function process(html: string, options: Options, re: Expressions): Part[] {
|
||||||
const parts: Part[] = compileBlock(html).parts
|
const parts: Part[] = compileBlock(html, options, re).parts
|
||||||
return parts
|
return parts
|
||||||
|
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ export interface ActionReturn {
|
|||||||
length: number
|
length: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ActionFunction = (part: Render) => ActionReturn
|
export type ActionFunction = (part: Render, options: Options, re: Expressions) => ActionReturn
|
||||||
|
|
||||||
export interface Compiled {
|
export interface Compiled {
|
||||||
template: Part[]
|
template: Part[]
|
||||||
@ -36,27 +36,21 @@ export const error = {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Options {
|
export interface Options {
|
||||||
encoding: string
|
encoding: string
|
||||||
caching: boolean
|
caching: boolean
|
||||||
template_dir: string
|
views: string
|
||||||
template_ext: string
|
extension: string
|
||||||
compiled_dir: string
|
|
||||||
compiled_ext: string
|
|
||||||
max_recursion: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const options: Options = {
|
export const options: Options = {
|
||||||
encoding: 'utf-8',
|
encoding: 'utf-8',
|
||||||
caching: true,
|
caching: true,
|
||||||
template_dir: './views',
|
views: './views',
|
||||||
template_ext: 'html',
|
extension: 'html',
|
||||||
compiled_dir: './cache',
|
|
||||||
compiled_ext: 'bjs',
|
|
||||||
max_recursion: 100,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Expressions {
|
export interface Expressions {
|
||||||
begin: string
|
begin: string
|
||||||
ending: string
|
ending: string
|
||||||
comment: string
|
comment: string
|
||||||
|
@ -2,7 +2,7 @@ import { Part, Render, isRender, PartFunction } from "./options";
|
|||||||
|
|
||||||
|
|
||||||
export function computeParts(parts: Part[], data = {}): Render {
|
export function computeParts(parts: Part[], data = {}): Render {
|
||||||
if (parts.length === 0)
|
if (parts === undefined || parts.length === 0)
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
return computePart(parts[0], data) + computeParts(parts.slice(1), data)
|
return computePart(parts[0], data) + computeParts(parts.slice(1), data)
|
||||||
|
42
src/util.ts
42
src/util.ts
@ -1,21 +1,11 @@
|
|||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as crypto from 'crypto'
|
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> {
|
export function readFile(url: string): Promise<string> {
|
||||||
return new Promise(res => {
|
return new Promise(res => {
|
||||||
fs.readFile(url, (err, data) => {
|
fs.readFile(url, (err, data) => {
|
||||||
if (err)
|
if (err)
|
||||||
throw new Error(`No such file: ${url}`)
|
res()
|
||||||
else
|
else
|
||||||
res(data.toString())
|
res(data.toString())
|
||||||
})
|
})
|
||||||
@ -26,21 +16,6 @@ export function readFileSync(url: string): string {
|
|||||||
return fs.readFileSync(url).toString()
|
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> {
|
export function fileExists(url: string): Promise<boolean> {
|
||||||
return new Promise(res => {
|
return new Promise(res => {
|
||||||
fs.exists(url, _ => {
|
fs.exists(url, _ => {
|
||||||
@ -57,6 +32,7 @@ export function checksum(url: string, plain = false, alg = 'sha1'): Promise<stri
|
|||||||
res(hash.update(url).digest('hex'))
|
res(hash.update(url).digest('hex'))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// For large files
|
||||||
const stream = fs.createReadStream(url)
|
const stream = fs.createReadStream(url)
|
||||||
stream.on('data', data => hash.update(data, 'utf8'))
|
stream.on('data', data => hash.update(data, 'utf8'))
|
||||||
stream.on('end', _ => { res(hash.digest('hex')) })
|
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 {
|
export function getFromObject(data: any, name: string): any {
|
||||||
|
|
||||||
name = name.trim()
|
name = name.trim()
|
||||||
@ -79,9 +51,11 @@ export function getFromObject(data: any, name: string): any {
|
|||||||
|
|
||||||
name = name.replace(/('|")/g, '')
|
name = name.replace(/('|")/g, '')
|
||||||
name = name.replace(/\[(\w+)\]/g, '.$1')
|
name = name.replace(/\[(\w+)\]/g, '.$1')
|
||||||
|
try {
|
||||||
for (const i of name.split('.'))
|
for (const i of name.split('.'))
|
||||||
data = data[i]
|
data = data[i]
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user