compile.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package ace
  2. import (
  3. "bytes"
  4. "fmt"
  5. "html/template"
  6. )
  7. // Actions
  8. const (
  9. actionDefine = `%sdefine "%s"%s`
  10. actionEnd = "%send%s"
  11. actionTemplate = `%stemplate "%s"%s`
  12. actionTemplateWithPipeline = `%stemplate "%s" %s%s`
  13. )
  14. // PreDefinedFuncs
  15. const (
  16. preDefinedFuncNameHTML = "HTML"
  17. )
  18. // CompileResult compiles the parsed result to the template.Template.
  19. func CompileResult(name string, rslt *result, opts *Options) (*template.Template, error) {
  20. // Initialize the options.
  21. opts = InitializeOptions(opts)
  22. // Create a template.
  23. t := template.New(name)
  24. return CompileResultWithTemplate(t, rslt, opts)
  25. }
  26. // CompileResultWithTemplate compiles the parsed result and associates it with t.
  27. func CompileResultWithTemplate(t *template.Template, rslt *result, opts *Options) (*template.Template, error) {
  28. // Initialize the options.
  29. opts = InitializeOptions(opts)
  30. var err error
  31. // Create a buffer.
  32. baseBf := bytes.NewBuffer(nil)
  33. innerBf := bytes.NewBuffer(nil)
  34. includeBfs := make(map[string]*bytes.Buffer)
  35. // Write data to the buffer.
  36. for _, e := range rslt.base {
  37. if _, err := e.WriteTo(baseBf); err != nil {
  38. return nil, err
  39. }
  40. }
  41. for _, e := range rslt.inner {
  42. if _, err = e.WriteTo(innerBf); err != nil {
  43. return nil, err
  44. }
  45. }
  46. for path, elements := range rslt.includes {
  47. bf := bytes.NewBuffer(nil)
  48. // Write a define action.
  49. bf.WriteString(fmt.Sprintf(actionDefine, opts.DelimLeft, path, opts.DelimRight))
  50. for _, e := range elements {
  51. if _, err = e.WriteTo(bf); err != nil {
  52. return nil, err
  53. }
  54. }
  55. // Write an end action.
  56. bf.WriteString(fmt.Sprintf(actionEnd, opts.DelimLeft, opts.DelimRight))
  57. includeBfs[path] = bf
  58. }
  59. // Set Delimiters.
  60. t.Delims(opts.DelimLeft, opts.DelimRight)
  61. // Set FuncMaps.
  62. t.Funcs(template.FuncMap{
  63. preDefinedFuncNameHTML: func(s string) template.HTML {
  64. return template.HTML(s)
  65. },
  66. })
  67. t.Funcs(opts.FuncMap)
  68. // Parse a string to the template.
  69. t, err = t.Parse(baseBf.String())
  70. if err != nil {
  71. return nil, err
  72. }
  73. t, err = t.Parse(innerBf.String())
  74. if err != nil {
  75. return nil, err
  76. }
  77. for _, bf := range includeBfs {
  78. t, err = t.Parse(bf.String())
  79. if err != nil {
  80. return nil, err
  81. }
  82. }
  83. return t, nil
  84. }