Compiler.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import pug from "pug";
  2. import fs from "fs";
  3. import path from "path";
  4. import { CompiledTemplate, Renderer } from "./Renderer";
  5. import Plugin from "./compiler/Plugin";
  6. export namespace Compiler {
  7. export interface Options {
  8. /**
  9. * If set to true, the function source will be included in the compiled template
  10. * for better error messages. It is not enabled by default.
  11. */
  12. debug?: boolean,
  13. /**
  14. * Any configurations to be passed to pug
  15. */
  16. pug?: pug.Options
  17. }
  18. }
  19. export default class PupperCompiler {
  20. /**
  21. * Compiles a template string into a renderer instance
  22. * @param template The template string to be compiled
  23. * @param options The compiler options
  24. * @returns
  25. */
  26. public compile(template: string, options: Compiler.Options = {}): Renderer {
  27. try {
  28. return new Renderer(
  29. pug.compile(template, this.getPugOptions(options)) as CompiledTemplate
  30. );
  31. } catch(e) {
  32. throw (options.debug ? e : new Error("Failed to compile template:" + e.message));
  33. }
  34. }
  35. /**
  36. * Compiles a single template file into a renderer instance
  37. * @param file The file to be compiled
  38. * @returns
  39. */
  40. public compileFile(file: string, options: Compiler.Options = {}): Renderer {
  41. const pugOptions = this.getPugOptions(options);
  42. pugOptions.basedir = path.dirname(file);
  43. pugOptions.filename = file;
  44. return this.compile(fs.readFileSync(file, "utf8"), pugOptions);
  45. }
  46. /**
  47. * Compiles a pupper template to a Javascript module
  48. * @param template The template to be compiled
  49. * @param options
  50. * @returns
  51. */
  52. public compileToString(template: string, options: Compiler.Options = {}): string {
  53. try {
  54. const pugOptions = this.getPugOptions(options);
  55. const rendered = pug.compileClient(template, pugOptions);
  56. return /*javascript*/`
  57. ${rendered}
  58. module.exports = ${pugOptions.name};
  59. `;
  60. } catch(e) {
  61. throw (options.debug ? e : new Error("Failed to compile template:" + e.message));
  62. }
  63. }
  64. /**
  65. * Parses the compiler options into pug options
  66. * and put our plugins into it
  67. * @param options The compiler options
  68. * @returns
  69. */
  70. private getPugOptions(options: Compiler.Options = {}): pug.Options {
  71. const pugOptions: pug.Options = {
  72. // We use "render" as the function name
  73. name: "render",
  74. // The default filename (when no filename is given) is template.pupper
  75. filename: "template.pupper",
  76. compileDebug: options.debug || false,
  77. // Always use self to prevent conflicts with other compilers
  78. self: true,
  79. plugins: [],
  80. ...options.pug
  81. };
  82. // Create a new parser for this pug instance
  83. pugOptions.plugins.push(
  84. new Plugin(pugOptions)
  85. );
  86. return pugOptions;
  87. }
  88. }