92 lines
2.7 KiB
CoffeeScript
92 lines
2.7 KiB
CoffeeScript
TEMPLATE_BUILTINS =
|
|
a: (text) ->
|
|
if text.match(/^[aeioAEIO]/)
|
|
return "an #{text}"
|
|
return "a #{text}"
|
|
an: (text) ->
|
|
return this.a(text)
|
|
cap: (text) ->
|
|
return "#{text[0].toUpperCase()}#{text.slice(1)}"
|
|
A: (text) ->
|
|
return this.cap(this.a(text))
|
|
An: (text) ->
|
|
return this.A(text)
|
|
|
|
mergeInTag = (tags, tag) ->
|
|
# Find the matching tag...
|
|
|
|
i = tags.findIndex(t => t[0] == tag[0])
|
|
|
|
if i == -1
|
|
return tags.concat([tag])
|
|
|
|
# Otherwise:
|
|
# This is supposed to be a non-destructive operation
|
|
newTags = tags.concat()
|
|
newTags[i] = tag
|
|
return newTags
|
|
|
|
processDirective = (rawDirective, model, cb, generator) ->
|
|
directive = rawDirective.trim()
|
|
|
|
if directive[0] == directive.slice(-1) && directive[0] == "'"
|
|
# This is a literal directive.
|
|
return directive.slice(1, -1)
|
|
|
|
if directive.indexOf(' ') != -1
|
|
# The directive contains a space, which means it's a chained directive.
|
|
funcName = directive.split(' ')[0]
|
|
rest = directive.slice(directive.indexOf(' ') + 1)
|
|
|
|
if TEMPLATE_BUILTINS.hasOwnProperty(funcName)
|
|
return "#{TEMPLATE_BUILTINS[funcName](processDirective(rest, model, cb, generator))}"
|
|
|
|
if generator && generator.builtins && generator.builtins[funcName]
|
|
return "#{generator.builtins[funcName](processDirective(rest, model, cb, generator))}"
|
|
|
|
if typeof model[funcName] != 'function'
|
|
throw new Error("Builtin or model property \"#{funcName}\" is not a function.")
|
|
|
|
return "#{model[funcName](processDirective(rest, model, cb, generator))}"
|
|
|
|
if directive[0] == '|'
|
|
[tagStr, snippet] = directive.split(':')
|
|
# Disregard the first |
|
|
newTag = tagStr.slice(1).split('|')
|
|
newModel = Object.create(model)
|
|
|
|
newModel.tags = mergeInTag(model.tags, newTag)
|
|
|
|
return cb(snippet, newModel)
|
|
|
|
if directive[0] == ':'
|
|
return cb(directive.slice(1), model)
|
|
|
|
if directive[0] == '#'
|
|
args = directive.slice(1).split('-')
|
|
return salet.rnd.randRange(parseInt(args[0], 10), parseInt(args[1], 10))
|
|
|
|
if directive.indexOf('.') != -1
|
|
propChain = directive.split('.')
|
|
return propChain.reduce((obj, prop) =>
|
|
return [obj[prop], model] ## TODO
|
|
)
|
|
|
|
return "#{model[directive]}"
|
|
|
|
template = (phrase, model, cb, generator) ->
|
|
[openBracket, closeBracket] = [phrase.indexOf('['), phrase.indexOf(']')]
|
|
if openBracket == -1
|
|
return phrase
|
|
if closeBracket == -1
|
|
throw new Error("Missing close bracket in phrase: #{phrase}")
|
|
before = phrase.slice(0, openBracket)
|
|
after = phrase.slice(closeBracket + 1)
|
|
directive = phrase.substring(openBracket + 1, closeBracket)
|
|
return template(
|
|
"#{before}#{processDirective(directive, model, cb, generator)}#{after}",
|
|
model,
|
|
cb,
|
|
generator
|
|
)
|