From 40d855d3ed00ef448ceb90bbbf25fa1115538f01 Mon Sep 17 00:00:00 2001 From: moe Date: Tue, 26 Mar 2024 23:12:53 +0100 Subject: [PATCH] Improve jinja2 error handling --- spec/envcat/cli/format/j2_spec.cr | 9 +++++++++ src/envcat/cli.cr | 2 +- src/envcat/format/j2.cr | 27 +++++++++++++++++---------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/spec/envcat/cli/format/j2_spec.cr b/spec/envcat/cli/format/j2_spec.cr index 790497b..90f7a6a 100644 --- a/spec/envcat/cli/format/j2_spec.cr +++ b/spec/envcat/cli/format/j2_spec.cr @@ -14,6 +14,15 @@ describe Envcat::Cli do } end + it "fails cleanly on 'empty expression' template error" do + tpl = "{{}}" + expect_output(/^$/, /^Malformed template:/, tpl) { |o, e, i| + expect_raises(Exit, "3") { + Envcat::Cli.invoke(%w[-f j2], o, e, i) + } + } + end + it "fails if any referenced var is undefined" do tpl = "{{FOO}} {{BAR}}" expect_output(/^$/, /Undefined variable: BAR/, tpl) { |o, e, i| diff --git a/src/envcat/cli.cr b/src/envcat/cli.cr index b3ad88d..e7e9ba4 100644 --- a/src/envcat/cli.cr +++ b/src/envcat/cli.cr @@ -225,7 +225,7 @@ class Envcat::Cli rescue ex : Format::UnknownFormatIdError io_err.puts "Unknown format: #{ex.message}" exit E_SYNTAX - rescue ex : Crinja::TemplateSyntaxError | Crinja::FeatureLibrary::UnknownFeatureError | Crinja::TypeError + rescue ex : Crinja::TemplateSyntaxError | Crinja::FeatureLibrary::UnknownFeatureError | Crinja::TypeError | Format::J2::RenderError io_err.puts "Malformed template: #{ex.message}" exit E_SYNTAX rescue ex : ParseException diff --git a/src/envcat/format/j2.cr b/src/envcat/format/j2.cr index 7a2942b..7c6bf49 100644 --- a/src/envcat/format/j2.cr +++ b/src/envcat/format/j2.cr @@ -3,7 +3,7 @@ require "crinja" # 🐒 class Crinja::Undefined - class_property strict = false # ameba:disable Style/QueryBoolMethods + class_property strict = false # ameba:disable Naming/QueryBoolMethods class_property tagged = [] of String def to_s(io) @@ -24,6 +24,8 @@ module Envcat class Format::J2 < Format::Formatter class UndefinedVariableError < Exception; end + class RenderError < Exception; end + @@strict = true def self.description : String @@ -37,18 +39,23 @@ module Envcat def write(env) Envcat.claim_stdin! if @io_in == STDIN - Crinja::Undefined.strict = @@strict + begin + Crinja::Undefined.strict = @@strict - crinja = Crinja.new(Crinja::Config.new(keep_trailing_newline: true)) + crinja = Crinja.new(Crinja::Config.new(keep_trailing_newline: true)) - crinja.filters["split"] = Crinja.filter({on: nil}) { target.to_s.split(arguments["on"].to_s) } - crinja.filters["b64encode"] = Crinja.filter { Base64.strict_encode(target.to_s) } - crinja.filters["b64encode_urlsafe"] = Crinja.filter { Base64.urlsafe_encode(target.to_s) } - crinja.filters["b64decode"] = Crinja.filter { Base64.decode_string(target.to_s) } + crinja.filters["split"] = Crinja.filter({on: nil}) { target.to_s.split(arguments["on"].to_s) } + crinja.filters["b64encode"] = Crinja.filter { Base64.strict_encode(target.to_s) } + crinja.filters["b64encode_urlsafe"] = Crinja.filter { Base64.urlsafe_encode(target.to_s) } + crinja.filters["b64decode"] = Crinja.filter { Base64.decode_string(target.to_s) } - buf = IO::Memory.new(16384) - IO.copy(@io_in, buf) - crinja.from_string(buf.to_s).render(@io, env.as(Envcat::Env)) + buf = IO::Memory.new(16384) + IO.copy(@io_in, buf) + crinja.from_string(buf.to_s).render(@io, env.as(Envcat::Env)) + rescue ex + raise ex if ex.is_a? Format::J2::UndefinedVariableError + raise RenderError.new(ex.message) + end end end end