feat: relativeReference for render/include/layout, #395

- `relativeReference` is enabled by default, set to `false` to disable
- Referenced files are still constrained within root/partias/layouts
- fix: relative filenames are not constrained (which allows arbitrary filesystem read)

Example Usage:

{% render "../foo/bar.html" %}

Note:

../foo/bar.html' should also be within `partials` (or `root` if `partials` not set)
This commit is contained in:
Harttle
2021-10-06 17:36:37 +08:00
parent 24a19c092a
commit a3455ebd0b
15 changed files with 160 additions and 31 deletions
+8 -6
View File
@@ -13,7 +13,7 @@ import { Loader, LookupType } from '../fs/loader'
import { FS } from '../fs/fs'
export default class Parser {
public parseFile: (file: string, sync?: boolean, type?: LookupType) => Iterator<Template[]>
public parseFile: (file: string, sync?: boolean, type?: LookupType, currentFile?: string) => Iterator<Template[]>
private liquid: Liquid
private fs: FS
@@ -56,17 +56,19 @@ export default class Parser {
public parseStream (tokens: TopLevelToken[]) {
return new ParseStream(tokens, (token, tokens) => this.parseToken(token, tokens))
}
private * _parseFileCached (file: string, sync?: boolean, type: LookupType = LookupType.Root) {
const key = type + ':' + file
private * _parseFileCached (file: string, sync?: boolean, type: LookupType = LookupType.Root, currentFile?: string) {
const key = this.loader.shouldLoadRelative(file)
? currentFile + ',' + file
: type + ':' + file
let templates = yield this.cache!.read(key)
if (templates) return templates
templates = yield this._parseFile(file, sync)
templates = yield this._parseFile(file, sync, type, currentFile)
this.cache!.write(key, templates)
return templates
}
private * _parseFile (file: string, sync?: boolean, type: LookupType = LookupType.Root) {
const filepath = yield this.loader.lookup(file, type, sync)
private * _parseFile (file: string, sync?: boolean, type: LookupType = LookupType.Root, currentFile?: string) {
const filepath = yield this.loader.lookup(file, type, sync, currentFile)
return this.liquid.parse(sync ? this.fs.readFileSync(filepath) : yield this.fs.readFile(filepath), filepath)
}
}