Skip to content

Commit

Permalink
refactor:render api.
Browse files Browse the repository at this point in the history
  • Loading branch information
chizuki committed Jul 25, 2022
1 parent 8fa726f commit 444cb6d
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 136 deletions.
30 changes: 30 additions & 0 deletions packages/core/src/element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export function createElement(tag: string, props: any = {}, ...children: string[]) {
if (!props || typeof props != "object" || Array.isArray(props)) {
props = {}
}

if (props.class && Array.isArray(props.class)) {
props.class = props.class.join(" ")
}

function renderChildren(children: string[]): string {
if (Array.isArray(children)) {
return children.map(c => (Array.isArray(c) ? renderChildren(c) : c)).join("")
}
return children
}

return (
"<" +
tag +
" " +
Object.entries(props)
.map(([k, v]) => `${k}="${v}"`)
.join(" ") +
">" +
renderChildren(children) +
"</" +
tag +
">"
)
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./app"
export * from "./element"
export * from "./logger"
export * from "./mock"
export * from "./shared"
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const LOGGER_LEVELS = {
}

export interface Logger {
setLevel(level: number | string): void
// info
info(...args: any[]): void
// debug
Expand All @@ -27,7 +28,6 @@ export interface Logger {
}

export interface FourzeLogger extends Logger {
setLevel(level: number): void
level: number
}

Expand Down
69 changes: 0 additions & 69 deletions packages/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,72 +63,3 @@ export function randomBoolean(): boolean {
export function randomItem<T>(source: T[]): T {
return source[randomInt(source.length)]
}

export const LOGGER_LEVELS = {
TRACE: 0,
DEBUG: 1,
INFO: 2,
WARN: 3,
ERROR: 4,
FATAL: 5,
ALL: Number.MIN_VALUE,
OFF: Number.MAX_VALUE
}

export interface Logger {
// info
info(...args: any[]): void
// debug
debug(...args: any[]): void
// warn
warn(...args: any[]): void
// error
error(...args: any[]): void
// fatal
fatal(...args: any[]): void
// trace
trace(...args: any[]): void
}

export interface FourzeLogger extends Logger {
setLevel(level: number): void
level: number
}

export const logger: FourzeLogger = {
level: LOGGER_LEVELS.ALL,
setLevel(level: number | string) {
this.level = typeof level === "string" ? LOGGER_LEVELS[level as keyof typeof LOGGER_LEVELS] ?? 0 : level
},
info(...args: any[]) {
if (this.level <= LOGGER_LEVELS.INFO) {
console.info(`[INFO ${dayjs().format("YYYY-MM-DD HH:mm:ss")}]`, ...args)
}
},
debug(...args: any[]) {
if (this.level <= LOGGER_LEVELS.DEBUG) {
console.debug(`[DEBUG ${dayjs().format("YYYY-MM-DD HH:mm:ss")}]`, ...args)
}
},
warn(...args: any[]) {
if (this.level <= LOGGER_LEVELS.WARN) {
console.warn(`[WARNING ${dayjs().format("YYYY-MM-DD HH:mm:ss")}]`, ...args)
}
},
trace(...args: any[]) {
if (this.level <= LOGGER_LEVELS.TRACE) {
console.trace(`[TRACE ${dayjs().format("YYYY-MM-DD HH:mm:ss")}]`, ...args)
}
},

error(...args: any[]) {
if (this.level <= LOGGER_LEVELS.ERROR) {
console.error(`[ERROR ${dayjs().format("YYYY-MM-DD HH:mm:ss")}]`, ...args)
}
},
fatal(...args: any[]) {
if (this.level <= LOGGER_LEVELS.FATAL) {
console.error(`[FATAL ${dayjs().format("YYYY-MM-DD HH:mm:ss")}]`, ...args)
}
}
}
31 changes: 19 additions & 12 deletions packages/server/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ export interface FourzeRendererOptions {

export type FourzeRenderer = FourzeMiddleware

export type FourzeRenderTemplate = (url: string) => any
export type FourzeRenderTemplate = (context: FourzeRendererContext) => any

export function renderFile(p: string) {
p = path.normalize(p)
export interface FourzeRendererContext {
path: string
request: FourzeRequest
response: FourzeResponse
}

export function renderFile(context: FourzeRendererContext) {
let p = context.path
const extensions = ["html", "htm"]
const maybes = [p].concat(extensions.map(ext => path.normalize(`${p}/index.${ext}`)))
do {
Expand All @@ -51,15 +57,15 @@ export function createRenderer(options: FourzeRendererOptions | string = {}): Fo
const templates = (options && typeof options == "object" ? options.templates : []) ?? []
const base = typeof options == "string" ? "/" : options.base ?? "/"
const _fallbacks = (options && typeof options == "object" ? options.fallbacks : []) ?? []
const fallbasks = Array.isArray(_fallbacks) ? _fallbacks.map(f => [f, f]) : Object.entries(_fallbacks)
const fallbacks = Array.isArray(_fallbacks) ? _fallbacks.map(f => [f, f]) : Object.entries(_fallbacks)
if (!templates.includes(renderFile)) {
templates.push(renderFile)
}

async function render(p: string) {
async function render(context: FourzeRendererContext) {
let content: Buffer | undefined
for (let template of templates) {
content = await template(p)
content = await template(context)
if (!!content) {
break
}
Expand All @@ -70,18 +76,19 @@ export function createRenderer(options: FourzeRendererOptions | string = {}): Fo
const renderer = async function (request: FourzeRequest, response: FourzeResponse, next?: () => void | Promise<void>) {
const url = request.relativePath
if (url.startsWith(base)) {
let p: string = path.join(dir, url)
const context = { path: path.join(dir, url), request, response }

let content = await render(p)
let content = await render(context)

if (!content) {
for (let [fr, to] of fallbasks) {
to = path.join(dir, to)
for (let [fr, to] of fallbacks) {
if (url.startsWith(fr)) {
content = await render(to)
to = path.normalize(path.join(dir, to))
context.path = to
content = await render(context)

if (!content) {
content = renderFile(to)
content = renderFile(context)
}

if (!!content) {
Expand Down
93 changes: 40 additions & 53 deletions playgrounds/server/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import comporession from "compression"
import ejs from "ejs"
import { transform } from "esbuild"

import { CommonMiddleware, createApp, createRenderer, createRouter } from "@fourze/server"
import { CommonMiddleware, createApp, createRenderer, createRouter, FourzeRendererContext } from "@fourze/server"
import fs from "fs"
import path from "path"

Expand All @@ -22,76 +22,63 @@ const router2 = createRouter(route => {
})
})

export async function renderEjs(p: string) {
const file = path.resolve(process.cwd(), path.normalize(p))
export async function renderEjs(context: FourzeRendererContext) {
const file = path.normalize(context.path)
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
return ejs.renderFile(file, {})
}
}

export function createFourzeElement(tag: string, props: any = {}, ...children: string[]) {
if (!props || typeof props != "object" || Array.isArray(props)) {
props = {}
}
export async function rendertsx(context: FourzeRendererContext) {
const file = path.normalize(context.path)

if (props.class && Array.isArray(props.class)) {
props.class = props.class.join(" ")
}
const maybes = [file].concat(["index.tsx", "index.jsx"].map(ext => path.normalize(`${file}/${ext}`)))

function renderChildren(children: string[]): string {
if (Array.isArray(children)) {
return children.map(c => (Array.isArray(c) ? renderChildren(c) : c)).join("")
}
return children
}
for (let maybe of maybes) {
if (fs.existsSync(maybe) && fs.statSync(maybe).isFile()) {
const raw = fs.readFileSync(maybe).toString()
const { code } = await transform(raw, {
target: "esnext",
format: "esm",
loader: "tsx",
banner: "import {createElement} from '@fourze/core'",

return (
"<" +
tag +
" " +
Object.entries(props)
.map(([k, v]) => `${k}="${v}"`)
.join(" ") +
">" +
renderChildren(children) +
"</" +
tag +
">"
)
}
tsconfigRaw: {
compilerOptions: {
jsxFactory: "createElement",
jsxFragmentFactory: "Fragment"
}
}
})

export async function rendertsx(p: string) {
const file = path.resolve(process.cwd(), path.normalize(p))
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
const raw = fs.readFileSync(file).toString()
const { code } = await transform(raw, {
target: "esnext",
format: "cjs",
loader: "tsx",
tsconfigRaw: {
compilerOptions: {
jsxFactory: "createFourzeElement",
jsxFragmentFactory: "Fragment"
const tmp = path.normalize(maybe.replace(".tsx", ".tmp.js"))

delete require.cache[tmp]

fs.writeFileSync(tmp, code)

const { default: mod } = await require(tmp)

const { render } = mod
fs.rmSync(tmp)

if (render && typeof render === "function") {
let content = await render()
if (typeof content == "function") {
content = content()
}
context.response.setHeader("Content-Type", "text/html; charset=utf-8")

return content
}
})

const { default: mod } = await eval(code)
const { render } = mod
if (render && typeof render === "function") {
let content = await render()
if (typeof content == "function") {
content = content()
}
return content
}
}
}

const renderer = createRenderer({ dir: path.resolve(process.cwd(), "../web/dist"), fallbacks: { "/home": "/" } })

const ejsRenderer = createRenderer({ templates: [renderEjs], fallbacks: { "/ejs": "/ejs/index.ejs" } })
const tsxRenderer = createRenderer({ templates: [rendertsx], fallbacks: { "/tsx": "/tsx/index.tsx" } })
const tsxRenderer = createRenderer({ templates: [rendertsx] })

const app = createApp({})

Expand Down
2 changes: 1 addition & 1 deletion playgrounds/server/tsx/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default {

return async () => {
return (
<div class={"w-4 ".concat("h-4")}>
<div class={"w-4 ".concat("h-4").concat(" m-4")}>
<div>{"Hello,World"}</div>
{list.map(item => (
<div>{item}</div>
Expand Down

0 comments on commit 444cb6d

Please sign in to comment.