@uiengine/adapter-html
Version:
UIengine template adapter for HTML.
65 lines (52 loc) • 1.92 kB
JavaScript
const { dirname, isAbsolute, join, resolve } = require('path')
const assert = require('assert')
const { FileUtil: { read } } = require('@uiengine/util')
const INCLUDE_REGEXP = /<!--#\s?include file="(.*?)".*?-->/
const INCLUDES_REGEXP = new RegExp(INCLUDE_REGEXP, 'g')
const resolveFilePath = (options, embeddingFilePath, filePath) => {
if (isAbsolute(filePath)) {
const { basedir } = options
assert(basedir, 'Please provide a "basedir" option for the HTML adapter to resolve absolute includes.')
return join(basedir, filePath)
} else {
const basedir = dirname(embeddingFilePath)
return resolve(basedir, filePath)
}
}
const resolveVariable = (data, varPath, varPathComps) => {
if (!varPathComps) {
varPathComps = varPath.split('.')
}
if (varPathComps.length === 0) {
return data
} else if (varPathComps.length === 1) {
const value = data[varPathComps[0]]
return value || `\${${varPath}}`
} else {
const prop = varPathComps.shift()
if (data[prop] === undefined) data[prop] = {}
return resolveVariable(data[prop], varPath, varPathComps)
}
}
const renderString = (str, data) =>
str.replace(/\$\{(.+?)\}/g, (match, varPath) => resolveVariable(data, varPath))
const renderFile = async (options, filePath, data) => {
const template = await read(filePath)
let html = renderString(template, data)
const matches = html.match(INCLUDES_REGEXP)
if (!matches) return html
await Promise.all(matches.map(async include => {
const [, includeFile] = include.match(INCLUDE_REGEXP)
const includePath = resolveFilePath(options, filePath, includeFile)
const contents = await renderFile(options, includePath, data)
html = html.replace(include, contents)
}))
return html
}
async function render (options, filePath, data = {}) {
const result = await renderFile(options, filePath, data)
return result
}
module.exports = {
render
}