Dynamic names support (#49)
* Dynamic names support * Add support for dynamic names in parent tags * Support all dynamic names spec * Swift 5.8 compile fix
This commit is contained in:
@@ -232,29 +232,55 @@ extension MustacheTemplate {
|
||||
case ">":
|
||||
// partial
|
||||
parser.unsafeAdvance()
|
||||
// skip whitespace
|
||||
parser.read(while: \.isWhitespace)
|
||||
var dynamic = false
|
||||
if parser.current() == "*" {
|
||||
parser.unsafeAdvance()
|
||||
dynamic = true
|
||||
}
|
||||
let name = try parsePartialName(&parser, state: state)
|
||||
if whiteSpaceBefore.count > 0 {
|
||||
tokens.append(.text(String(whiteSpaceBefore)))
|
||||
}
|
||||
if self.isStandalone(&parser, state: state) {
|
||||
setNewLine = true
|
||||
tokens.append(.partial(name, indentation: String(whiteSpaceBefore), inherits: nil))
|
||||
if dynamic {
|
||||
tokens.append(.dynamicNamePartial(name, indentation: String(whiteSpaceBefore), inherits: nil))
|
||||
} else {
|
||||
tokens.append(.partial(name, indentation: String(whiteSpaceBefore), inherits: nil))
|
||||
}
|
||||
} else {
|
||||
tokens.append(.partial(name, indentation: nil, inherits: nil))
|
||||
if dynamic {
|
||||
tokens.append(.dynamicNamePartial(name, indentation: nil, inherits: nil))
|
||||
} else {
|
||||
tokens.append(.partial(name, indentation: nil, inherits: nil))
|
||||
}
|
||||
}
|
||||
whiteSpaceBefore = ""
|
||||
|
||||
case "<":
|
||||
// partial with inheritance
|
||||
parser.unsafeAdvance()
|
||||
let name = try parsePartialName(&parser, state: state)
|
||||
// skip whitespace
|
||||
parser.read(while: \.isWhitespace)
|
||||
let sectionName = try parsePartialName(&parser, state: state)
|
||||
let name: String
|
||||
let dynamic: Bool
|
||||
if sectionName.first == "*" {
|
||||
dynamic = true
|
||||
name = String(sectionName.dropFirst())
|
||||
} else {
|
||||
dynamic = false
|
||||
name = sectionName
|
||||
}
|
||||
if whiteSpaceBefore.count > 0 {
|
||||
tokens.append(.text(String(whiteSpaceBefore)))
|
||||
}
|
||||
if self.isStandalone(&parser, state: state) {
|
||||
setNewLine = true
|
||||
}
|
||||
let sectionTokens = try parse(&parser, state: state.withInheritancePartial(name))
|
||||
let sectionTokens = try parse(&parser, state: state.withInheritancePartial(sectionName))
|
||||
var inherit: [String: MustacheTemplate] = [:]
|
||||
// parse tokens in section to extract inherited sections
|
||||
for token in sectionTokens {
|
||||
@@ -267,7 +293,11 @@ extension MustacheTemplate {
|
||||
throw Error.illegalTokenInsideInheritSection
|
||||
}
|
||||
}
|
||||
tokens.append(.partial(name, indentation: String(whiteSpaceBefore), inherits: inherit))
|
||||
if dynamic {
|
||||
tokens.append(.dynamicNamePartial(name, indentation: String(whiteSpaceBefore), inherits: inherit))
|
||||
} else {
|
||||
tokens.append(.partial(name, indentation: String(whiteSpaceBefore), inherits: inherit))
|
||||
}
|
||||
whiteSpaceBefore = ""
|
||||
|
||||
case "$":
|
||||
@@ -478,7 +508,7 @@ extension MustacheTemplate {
|
||||
return state.newLine && self.hasLineFinished(&parser)
|
||||
}
|
||||
|
||||
private static let sectionNameCharsWithoutBrackets = Set<Character>("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_?")
|
||||
private static let sectionNameChars = Set<Character>("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_?()")
|
||||
private static let sectionNameCharsWithoutBrackets = Set<Character>("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_?*")
|
||||
private static let sectionNameChars = Set<Character>("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_?()*")
|
||||
private static let partialNameChars = Set<Character>("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_()")
|
||||
}
|
||||
|
||||
@@ -101,6 +101,28 @@ extension MustacheTemplate {
|
||||
return template.render(context: context.withPartial(indented: indentation, inheriting: overrides))
|
||||
}
|
||||
|
||||
case .dynamicNamePartial(let name, let indentation, let overrides):
|
||||
let child = self.getChild(named: name, transforms: [], context: context)
|
||||
guard let childName = child as? String else {
|
||||
return ""
|
||||
}
|
||||
if var template = context.library?.getTemplate(named: childName) {
|
||||
#if DEBUG
|
||||
if context.reloadPartials {
|
||||
guard let filename = template.filename else {
|
||||
preconditionFailure("Can only use reload if template was generated from a file")
|
||||
}
|
||||
do {
|
||||
guard let partialTemplate = try MustacheTemplate(filename: filename) else { return "Cannot find template at \(filename)" }
|
||||
template = partialTemplate
|
||||
} catch {
|
||||
return "\(error)"
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return template.render(context: context.withPartial(indented: indentation, inheriting: overrides))
|
||||
}
|
||||
|
||||
case .contentType(let contentType):
|
||||
context = context.withContentType(contentType)
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ public struct MustacheTemplate: Sendable {
|
||||
case blockDefinition(name: String, template: MustacheTemplate)
|
||||
case blockExpansion(name: String, default: MustacheTemplate, indentation: String?)
|
||||
case partial(String, indentation: String?, inherits: [String: MustacheTemplate]?)
|
||||
case dynamicNamePartial(String, indentation: String?, inherits: [String: MustacheTemplate]?)
|
||||
case contentType(MustacheContentType)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user