Skip to content

Commit

Permalink
refactor: cleanup and performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Aug 8, 2023
1 parent 5ca1e06 commit c3adc4f
Show file tree
Hide file tree
Showing 40 changed files with 397 additions and 624 deletions.
2 changes: 1 addition & 1 deletion bin/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { BASE_URL } from '../test_helpers/index.js'
*/
processCLIArgs(process.argv.slice(2))
configure({
files: ['test/**/*.spec.ts'],
files: ['tests/**/*.spec.ts'],
plugins: [assert(), fileSystem({ basePath: BASE_URL })],
})

Expand Down
2 changes: 1 addition & 1 deletion index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { Edge } from './src/edge/index.js'
import { safeValue } from './src/template/index.js'
import { safeValue } from './src/template.js'
import { GLOBALS } from './src/edge/globals/index.js'

/**
Expand Down
8 changes: 4 additions & 4 deletions src/cache_manager/index.ts → src/cache_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
* file that was distributed with this source code.
*/

import type { LoaderTemplate, CacheManagerContract } from '../types.js'
import type { CacheManagerContract, CompiledTemplate } from './types.js'

/**
* In memory cache manager to cache pre-compiled templates.
*/
export class CacheManager implements CacheManagerContract {
#cacheStore: Map<string, LoaderTemplate> = new Map()
#cacheStore: Map<string, CompiledTemplate> = new Map()

constructor(public enabled: boolean) {}

Expand All @@ -29,7 +29,7 @@ export class CacheManager implements CacheManagerContract {
* Returns the template from the cache. If caching is disabled,
* then it will return undefined.
*/
get(absPath: string): undefined | LoaderTemplate {
get(absPath: string): undefined | CompiledTemplate {
if (!this.enabled) {
return
}
Expand All @@ -41,7 +41,7 @@ export class CacheManager implements CacheManagerContract {
* Set's the template path and the payload to the cache. If
* cache is disabled, then this function results in a noop.
*/
set(absPath: string, payload: LoaderTemplate) {
set(absPath: string, payload: CompiledTemplate) {
if (!this.enabled) {
return
}
Expand Down
78 changes: 54 additions & 24 deletions src/compiler/index.ts → src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,38 @@
*/

import { EdgeError } from 'edge-error'
import * as lexerUtils from 'edge-lexer/utils'
import { Parser, EdgeBuffer, Stack } from 'edge-parser'
import type { Token, TagToken } from 'edge-lexer/types'
import * as lexerUtils from 'edge-lexer/utils'
import { Processor } from '../processor/index.js'
import { CacheManager } from '../cache_manager/index.js'

import { Processor } from './processor.js'
import { CacheManager } from './cache_manager.js'
import type {
ClaimTagFn,
TagsContract,
LoaderContract,
LoaderTemplate,
CompilerOptions,
CompilerContract,
} from '../types.js'
CompiledTemplate,
} from './types.js'

const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor

/**
* Compiler is to used to compile templates using the `edge-parser`. Along with that
* it natively merges the contents of a layout with a parent template.
*/
export class Compiler implements CompilerContract {
export class Compiler {
/**
* The variables someone can access inside templates. All other
* variables will get prefixed with `state` property name
*/
#inlineVariables: string[] = ['$filename', 'state', '$context']

/**
* A fixed set of params to pass to the template every time.
*/
#templateParams = ['template', 'state', '$context']

#claimTagFn?: ClaimTagFn
#loader: LoaderContract
#tags: TagsContract
Expand All @@ -38,7 +51,7 @@ export class Compiler implements CompilerContract {
cacheManager: CacheManager

/**
* Know if compiler is compiling for the async mode or not
* Know if compiler is compiling in the async mode or not
*/
async: boolean

Expand Down Expand Up @@ -183,7 +196,8 @@ export class Compiler implements CompilerContract {
async: this.async,
statePropertyName: 'state',
escapeCallPath: ['template', 'escape'],
localVariables: ['$filename', 'state', '$context'],
toAttributesCallPath: ['template', 'toAttributes'],
localVariables: this.#inlineVariables,
onTag: (tag) => this.#processor.executeTag({ tag, path: templatePath }),
})

Expand All @@ -209,6 +223,19 @@ export class Compiler implements CompilerContract {
})
}

/**
* Wraps template output to a function along with local variables
*/
#wrapToFunction(template: string, localVariables?: string[]): CompiledTemplate {
const args = localVariables ? this.#templateParams.concat(localVariables) : this.#templateParams

if (this.async) {
return new AsyncFunction(...args, template)
}

return new Function(...args, template) as CompiledTemplate
}

/**
* Define a function to claim tags
*/
Expand Down Expand Up @@ -252,9 +279,9 @@ export class Compiler implements CompilerContract {
* compiler.compile('welcome')
* ```
*/
compile(templatePath: string, localVariables?: string[], skipCache = false): LoaderTemplate {
compile(templatePath: string, localVariables?: string[]): CompiledTemplate {
const absPath = this.#loader.makePath(templatePath)
let cachedResponse = skipCache ? null : this.cacheManager.get(absPath)
let cachedResponse = localVariables ? null : this.cacheManager.get(absPath)

/**
* Process the template and cache it
Expand All @@ -269,20 +296,23 @@ export class Compiler implements CompilerContract {
const templateTokens = this.tokenize(absPath, parser)
templateTokens.forEach((token) => parser.processToken(token, buffer))

const template = buffer.flush()
if (!skipCache) {
this.cacheManager.set(absPath, { template })
/**
* Processing template via hook
*/
const template = this.#processor.executeCompiled({
path: absPath,
compiled: buffer.flush(),
})

const compiledTemplate = this.#wrapToFunction(template, localVariables)
if (!localVariables) {
this.cacheManager.set(absPath, compiledTemplate)
}

cachedResponse = { template }
cachedResponse = compiledTemplate
}

const template = this.#processor.executeCompiled({
path: absPath,
compiled: cachedResponse.template,
})

return { template }
return cachedResponse!
}

/**
Expand All @@ -291,10 +321,10 @@ export class Compiler implements CompilerContract {
* handles layouts.
*
* ```js
* compiler.compile('welcome')
* compiler.compileRaw('welcome')
* ```
*/
compileRaw(contents: string, templatePath: string = 'eval.edge'): LoaderTemplate {
compileRaw(contents: string, templatePath: string = 'eval.edge'): CompiledTemplate {
const parser = this.#getParserFor(templatePath)
const buffer = this.#getBufferFor(templatePath)
const templateTokens = this.tokenizeRaw(contents, templatePath, parser)
Expand All @@ -306,6 +336,6 @@ export class Compiler implements CompilerContract {
compiled: buffer.flush(),
})

return { template }
return this.#wrapToFunction(template)
}
}
8 changes: 4 additions & 4 deletions src/component/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import lodash from '@poppinss/utils/lodash'
import stringifyAttributes from 'stringify-attributes'

import { safeValue } from '../template/index.js'
import { htmlSafe } from '../template.js'
import { PropsContract } from '../types.js'

/**
Expand Down Expand Up @@ -102,7 +102,7 @@ export class Props implements PropsContract {
? lodash.merge({}, this.all(), mergeProps)
: lodash.merge({}, mergeProps, this.all())

return safeValue(stringifyAttributes(this.#mergeClassAttributes(attributes)))
return htmlSafe(stringifyAttributes(this.#mergeClassAttributes(attributes)))
}

/**
Expand All @@ -116,7 +116,7 @@ export class Props implements PropsContract {
? lodash.merge({}, this.only(keys), mergeProps)
: lodash.merge({}, mergeProps, this.only(keys))

return safeValue(stringifyAttributes(this.#mergeClassAttributes(attributes)))
return htmlSafe(stringifyAttributes(this.#mergeClassAttributes(attributes)))
}

/**
Expand All @@ -130,6 +130,6 @@ export class Props implements PropsContract {
? lodash.merge({}, this.except(keys), mergeProps)
: lodash.merge({}, mergeProps, this.except(keys))

return safeValue(stringifyAttributes(this.#mergeClassAttributes(attributes)))
return htmlSafe(stringifyAttributes(this.#mergeClassAttributes(attributes)))
}
}
6 changes: 3 additions & 3 deletions src/edge/globals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import inspect from '@poppinss/inspect'
const { string: prettyPrintHtml } = inspect
import string from '@poppinss/utils/string'

import { safeValue, escape } from '../../template/index.js'
import { htmlSafe, escape } from '../../template.js'

export const GLOBALS = {
/**
Expand All @@ -33,7 +33,7 @@ export const GLOBALS = {
* Inspect state
*/
inspect: (value: any) => {
return safeValue(prettyPrintHtml.html(value))
return htmlSafe(prettyPrintHtml.html(value))
},

/**
Expand Down Expand Up @@ -90,7 +90,7 @@ export const GLOBALS = {
* whereas this method converts it to an actual instance of date
*/
stringify: stringify,
safe: safeValue,
safe: htmlSafe,
camelCase: string.camelCase,
snakeCase: string.snakeCase,
dashCase: string.dashCase,
Expand Down
12 changes: 6 additions & 6 deletions src/edge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
* file that was distributed with this source code.
*/

import * as Tags from '../tags/index.js'
import { Loader } from '../loader/index.js'
import { Compiler } from '../compiler/index.js'
import { Template } from '../template/index.js'
import { Processor } from '../processor/index.js'
import { EdgeRenderer } from '../renderer/index.js'
import * as Tags from '../tags/main.js'
import { Loader } from '../loader.js'
import { Compiler } from '../compiler.js'
import { Template } from '../template.js'
import { Processor } from '../processor.js'
import { EdgeRenderer } from '../renderer.js'

import {
TagContract,
Expand Down
2 changes: 1 addition & 1 deletion src/loader/index.ts → src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import { readFileSync } from 'node:fs'
import { join, isAbsolute } from 'node:path'
import type { LoaderContract, LoaderTemplate } from '../types.js'
import type { LoaderContract, LoaderTemplate } from './types.js'

/**
* The job of a loader is to load the template from a given path.
Expand Down
12 changes: 4 additions & 8 deletions src/processor/index.ts → src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
* file that was distributed with this source code.
*/

import type { Template } from './template.js'
import type { TagToken } from 'edge-lexer/types'
import { ProcessorContract, TemplateContract } from '../types.js'

/**
* Exposes the API to register a set of handlers to process the
* templates output at different stages
*/
export class Processor implements ProcessorContract {
export class Processor {
#handlers: Map<string, Set<(...args: any[]) => any>> = new Map()

/**
Expand Down Expand Up @@ -72,11 +72,7 @@ export class Processor implements ProcessorContract {
/**
* Execute output handlers
*/
executeOutput(data: {
output: string
template: TemplateContract
state: Record<string, any>
}): string {
executeOutput(data: { output: string; template: Template; state: Record<string, any> }): string {
const handlers = this.#handlers.get('output')
if (!handlers) {
return data.output
Expand Down Expand Up @@ -105,7 +101,7 @@ export class Processor implements ProcessorContract {
event: 'output',
handler: (data: {
output: string
template: TemplateContract
template: Template
state: Record<string, any>
}) => string | void
): this
Expand Down
19 changes: 7 additions & 12 deletions src/renderer/index.ts → src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,21 @@

import lodash from '@poppinss/utils/lodash'

import { Template } from '../template/index.js'
import { Processor } from '../processor/index.js'
import { EdgeRendererContract, CompilerContract } from '../types.js'
import { Template } from './template.js'
import { Processor } from './processor.js'
import type { Compiler } from './compiler.js'

/**
* Renders a given template with it's shared state
*/
export class EdgeRenderer implements EdgeRendererContract {
export class EdgeRenderer {
#locals: any = {}
#compiler: CompilerContract
#asyncCompiler: CompilerContract
#compiler: Compiler
#asyncCompiler: Compiler
#globals: any
#processor: Processor

constructor(
compiler: CompilerContract,
asyncCompiler: CompilerContract,
globals: any,
processor: Processor
) {
constructor(compiler: Compiler, asyncCompiler: Compiler, globals: any, processor: Processor) {
this.#compiler = compiler
this.#asyncCompiler = asyncCompiler
this.#globals = globals
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions src/tags/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import * as lexerUtils from 'edge-lexer/utils'
import { EdgeBuffer, expressions, Parser } from 'edge-parser'

import { TagContract } from '../types.js'
import { StringifiedObject } from '../stringified_object/index.js'
import { isSubsetOf, unallowedExpression, parseJsArg } from '../utils/index.js'
import { StringifiedObject } from '../stringified_object.js'
import { isSubsetOf, unallowedExpression, parseJsArg } from '../utils.js'

/**
* A list of allowed expressions for the component name
Expand Down
2 changes: 1 addition & 1 deletion src/tags/each.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import * as lexerUtils from 'edge-lexer/utils'
import { Parser, expressions } from 'edge-parser'

import { TagContract } from '../types.js'
import { isSubsetOf, asyncEach, each, unallowedExpression } from '../utils/index.js'
import { isSubsetOf, asyncEach, each, unallowedExpression } from '../utils.js'

/**
* Returns the list to loop over for the each binary expression
Expand Down
2 changes: 1 addition & 1 deletion src/tags/else_if.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import { expressions } from 'edge-parser'
import { TagContract } from '../types.js'
import { isNotSubsetOf, unallowedExpression, parseJsArg } from '../utils/index.js'
import { isNotSubsetOf, unallowedExpression, parseJsArg } from '../utils.js'

/**
* Else if tag is used to define conditional blocks. We keep `@elseif` tag
Expand Down
Loading

0 comments on commit c3adc4f

Please sign in to comment.