diff --git a/lib/hanami/cli/commands/app/generate/action.rb b/lib/hanami/cli/commands/app/generate/action.rb index 226aea86..3e963ee7 100644 --- a/lib/hanami/cli/commands/app/generate/action.rb +++ b/lib/hanami/cli/commands/app/generate/action.rb @@ -28,6 +28,9 @@ class Action < App::Command DEFAULT_SKIP_ROUTE = false private_constant :DEFAULT_SKIP_ROUTE + DEFAULT_TEMPLATE = "erb" + private_constant :DEFAULT_TEMPLATE + argument :name, required: true, desc: "Action name" option :url, required: false, type: :string, desc: "Action URL" option :http, required: false, type: :string, desc: "Action HTTP method" @@ -51,6 +54,8 @@ class Action < App::Command default: DEFAULT_SKIP_ROUTE, desc: "Skip route generation" option :slice, required: false, desc: "Slice name" + option :template, required: false, type: :string, default: DEFAULT_TEMPLATE, + desc: "Template engine to use (officially supported options: erb, haml, slim)" # rubocop:disable Layout/LineLength example [ @@ -94,6 +99,7 @@ def call( skip_view: DEFAULT_SKIP_VIEW, skip_tests: DEFAULT_SKIP_TESTS, # rubocop:disable Lint/UnusedMethodArgument, skip_route: DEFAULT_SKIP_ROUTE, + template: DEFAULT_TEMPLATE, slice: nil, context: nil, ** @@ -106,7 +112,8 @@ def call( raise InvalidActionNameError.new(name) end - generator.call(app.namespace, controller, action, url, http, format, skip_view, skip_route, slice, context: context) + generator.call(app.namespace, controller, action, url, http, format, skip_view, skip_route, template, slice, + context: context) end # rubocop:enable Metrics/ParameterLists diff --git a/lib/hanami/cli/commands/app/generate/view.rb b/lib/hanami/cli/commands/app/generate/view.rb index 358ff11b..9c0bf107 100644 --- a/lib/hanami/cli/commands/app/generate/view.rb +++ b/lib/hanami/cli/commands/app/generate/view.rb @@ -18,10 +18,10 @@ class View < App::Command DEFAULT_FORMAT = "html" private_constant :DEFAULT_FORMAT - # TODO: make engine configurable - argument :name, required: true, desc: "View name" option :slice, required: false, desc: "Slice name" + option :template, required: false, desc: "Template engine to use (officially supported: erb, haml, slim)", + default: "erb" example [ %(books.index (MyApp::Actions::Books::Index)), @@ -43,10 +43,10 @@ def initialize( # @since 2.0.0 # @api private - def call(name:, format: DEFAULT_FORMAT, slice: nil, **) + def call(name:, format: DEFAULT_FORMAT, template: "erb", slice: nil, **) slice = inflector.underscore(Shellwords.shellescape(slice)) if slice - generator.call(app.namespace, name, format, slice) + generator.call(app.namespace, name, format, template, slice) end end end diff --git a/lib/hanami/cli/generators/app/action.rb b/lib/hanami/cli/generators/app/action.rb index 6e18da7f..dc8372c4 100644 --- a/lib/hanami/cli/generators/app/action.rb +++ b/lib/hanami/cli/generators/app/action.rb @@ -21,12 +21,12 @@ def initialize(fs:, inflector:) # @since 2.0.0 # @api private - def call(app, controller, action, url, http, format, skip_view, skip_route, slice, context: nil) + def call(app, controller, action, url, http, format, skip_view, skip_route, engine, slice, context: nil) context ||= ActionContext.new(inflector, app, slice, controller, action) if slice - generate_for_slice(controller, action, url, http, format, skip_view, skip_route, slice, context) + generate_for_slice(controller, action, url, http, format, skip_view, skip_route, engine, slice, context) else - generate_for_app(controller, action, url, http, format, skip_view, skip_route, context) + generate_for_app(controller, action, url, http, format, skip_view, skip_route, engine, context) end end @@ -72,7 +72,8 @@ def call(app, controller, action, url, http, format, skip_view, skip_route, slic attr_reader :inflector # rubocop:disable Metrics/AbcSize - def generate_for_slice(controller, action, url, http, format, skip_view, skip_route, slice, context) + def generate_for_slice(controller, action, url, http, format, skip_view, skip_route, engine, slice, + context) slice_directory = fs.join("slices", slice) raise MissingSliceError.new(slice) unless fs.directory?(slice_directory) @@ -92,12 +93,12 @@ def generate_for_slice(controller, action, url, http, format, skip_view, skip_ro fs.create(fs.join(directory, "#{action}.rb"), t("slice_view.erb", context)) fs.mkdir(directory = fs.join(slice_directory, "templates", controller)) - fs.create(fs.join(directory, "#{action}.#{format}.erb"), - t(template_with_format_ext("slice_template", format), context)) + fs.create(fs.join(directory, "#{action}.#{format}.#{engine}"), + t(template_with_format_ext("slice_template", format, engine), context)) end end - def generate_for_app(controller, action, url, http, format, skip_view, skip_route, context) + def generate_for_app(controller, action, url, http, format, skip_view, skip_route, engine, context) if generate_route?(skip_route) fs.inject_line_at_class_bottom( fs.join("config", "routes.rb"), @@ -117,8 +118,8 @@ def generate_for_app(controller, action, url, http, format, skip_view, skip_rout fs.create(fs.join(view_directory, "#{view}.rb"), t("view.erb", context)) fs.mkdir(template_directory = fs.join("app", "templates", controller)) - fs.create(fs.join(template_directory, "#{view}.#{format}.erb"), - t(template_with_format_ext("template", format), context)) + fs.create(fs.join(template_directory, "#{view}.#{format}.#{engine}"), + t(template_with_format_ext("template", format, engine), context)) end end # rubocop:enable Metrics/AbcSize @@ -169,13 +170,13 @@ def corresponding_restful_view(view) RESTFUL_COUNTERPART_VIEWS.fetch(view, nil) end - def template_with_format_ext(name, format) + def template_with_format_ext(name, format, engine) ext = case format.to_sym when :html - ".html.erb" + ".html.#{engine}" else - ".erb" + ".#{engine}" end "#{name}#{ext}" diff --git a/lib/hanami/cli/generators/app/action/slice_template.html.haml b/lib/hanami/cli/generators/app/action/slice_template.html.haml new file mode 100644 index 00000000..ed317a48 --- /dev/null +++ b/lib/hanami/cli/generators/app/action/slice_template.html.haml @@ -0,0 +1 @@ +%h1= <%= camelized_slice_name %>::Views::<%= camelized_controller_name %>::<%= camelized_action_name %> diff --git a/lib/hanami/cli/generators/app/action/slice_template.html.slim b/lib/hanami/cli/generators/app/action/slice_template.html.slim new file mode 100644 index 00000000..cd07aceb --- /dev/null +++ b/lib/hanami/cli/generators/app/action/slice_template.html.slim @@ -0,0 +1 @@ +h1 = <%= camelized_slice_name %>::Views::<%= camelized_controller_name %>::<%= camelized_action_name %> diff --git a/lib/hanami/cli/generators/app/action/template.html.haml b/lib/hanami/cli/generators/app/action/template.html.haml new file mode 100644 index 00000000..d75914c5 --- /dev/null +++ b/lib/hanami/cli/generators/app/action/template.html.haml @@ -0,0 +1 @@ +%h1= <%= camelized_app_name %>::Views::<%= camelized_controller_name %>::<%= camelized_action_name %> diff --git a/lib/hanami/cli/generators/app/action/template.html.slim b/lib/hanami/cli/generators/app/action/template.html.slim new file mode 100644 index 00000000..604af63c --- /dev/null +++ b/lib/hanami/cli/generators/app/action/template.html.slim @@ -0,0 +1 @@ +h1 = <%= camelized_app_name %>::Views::<%= camelized_controller_name %>::<%= camelized_action_name %> diff --git a/lib/hanami/cli/generators/app/view.rb b/lib/hanami/cli/generators/app/view.rb index f6675438..a34849f3 100644 --- a/lib/hanami/cli/generators/app/view.rb +++ b/lib/hanami/cli/generators/app/view.rb @@ -20,13 +20,13 @@ def initialize(fs:, inflector:) # @since 2.0.0 # @api private - def call(app, key, format, slice) + def call(app, key, format, engine, slice) context = ViewContext.new(inflector, app, slice, key) if slice - generate_for_slice(context, format, slice) + generate_for_slice(context, format, engine, slice) else - generate_for_app(context, format, slice) + generate_for_app(context, format, engine, slice) end end @@ -38,7 +38,7 @@ def call(app, key, format, slice) # rubocop:disable Metrics/AbcSize - def generate_for_slice(context, format, slice) + def generate_for_slice(context, format, engine, slice) slice_directory = fs.join("slices", slice) raise MissingSliceError.new(slice) unless fs.directory?(slice_directory) @@ -46,28 +46,28 @@ def generate_for_slice(context, format, slice) fs.create(fs.join(directory, "#{context.name}.rb"), t("slice_view.erb", context)) fs.mkdir(directory = fs.join(slice_directory, "templates", context.namespaces)) - fs.create(fs.join(directory, "#{context.name}.#{format}.erb"), - t(template_with_format_ext("slice_template", format), context)) + fs.create(fs.join(directory, "#{context.name}.#{format}.#{engine}"), + t(template_with_format_ext("slice_template", format, engine), context)) end - def generate_for_app(context, format, _slice) + def generate_for_app(context, format, engine, _slice) fs.mkdir(directory = fs.join("app", "views", context.namespaces)) fs.create(fs.join(directory, "#{context.name}.rb"), t("app_view.erb", context)) fs.mkdir(directory = fs.join("app", "templates", context.namespaces)) - fs.create(fs.join(directory, "#{context.name}.#{format}.erb"), - t(template_with_format_ext("app_template", format), context)) + fs.create(fs.join(directory, "#{context.name}.#{format}.#{engine}"), + t(template_with_format_ext("app_template", format, engine), context)) end # rubocop:enable Metrics/AbcSize - def template_with_format_ext(name, format) + def template_with_format_ext(name, format, engine) ext = case format.to_sym when :html - ".html.erb" + ".html.#{engine}" else - ".erb" + ".#{engine}" end "#{name}#{ext}" diff --git a/lib/hanami/cli/generators/app/view/app_template.html.haml b/lib/hanami/cli/generators/app/view/app_template.html.haml new file mode 100644 index 00000000..55b809db --- /dev/null +++ b/lib/hanami/cli/generators/app/view/app_template.html.haml @@ -0,0 +1 @@ +%h1 <%= camelized_app_name %>::Views::<%= camelized_namespace %>::<%= camelized_name %> diff --git a/lib/hanami/cli/generators/app/view/app_template.html.slim b/lib/hanami/cli/generators/app/view/app_template.html.slim new file mode 100644 index 00000000..fd6073ff --- /dev/null +++ b/lib/hanami/cli/generators/app/view/app_template.html.slim @@ -0,0 +1 @@ +h1 <%= camelized_app_name %>::Views::<%= camelized_namespace %>::<%= camelized_name %> diff --git a/lib/hanami/cli/generators/app/view/slice_template.html.haml b/lib/hanami/cli/generators/app/view/slice_template.html.haml new file mode 100644 index 00000000..066657bd --- /dev/null +++ b/lib/hanami/cli/generators/app/view/slice_template.html.haml @@ -0,0 +1 @@ +%h1 <%= camelized_slice_name %>::Views::<%= camelized_namespace %>::<%= camelized_name %> diff --git a/lib/hanami/cli/generators/app/view/slice_template.html.slim b/lib/hanami/cli/generators/app/view/slice_template.html.slim new file mode 100644 index 00000000..e3539260 --- /dev/null +++ b/lib/hanami/cli/generators/app/view/slice_template.html.slim @@ -0,0 +1 @@ +h1 <%= camelized_slice_name %>::Views::<%= camelized_namespace %>::<%= camelized_name %> diff --git a/spec/unit/hanami/cli/commands/app/generate/action_spec.rb b/spec/unit/hanami/cli/commands/app/generate/action_spec.rb index f9561e97..624c4042 100644 --- a/spec/unit/hanami/cli/commands/app/generate/action_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/action_spec.rb @@ -297,6 +297,28 @@ def handle(request, response) end end + it "allows to specify slim template engine" do + within_application_directory do + subject.call(name: action_name, template: "slim") + + template_file = <<~EXPECTED + h1 = Test::Views::Users::Index + EXPECTED + expect(fs.read("app/templates/#{controller}/#{action}.html.slim")).to eq(template_file) + end + end + + it "allows to specify HAML template engine" do + within_application_directory do + subject.call(name: action_name, template: "haml") + + template_file = <<~EXPECTED + %h1= Test::Views::Users::Index + EXPECTED + expect(fs.read("app/templates/#{controller}/#{action}.html.haml")).to eq(template_file) + end + end + include_context "with existing files" do let(:generate_action) { subject.call(name: action_name) } end diff --git a/spec/unit/hanami/cli/commands/app/generate/view_spec.rb b/spec/unit/hanami/cli/commands/app/generate/view_spec.rb index b761979f..42dc9085 100644 --- a/spec/unit/hanami/cli/commands/app/generate/view_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/view_spec.rb @@ -92,6 +92,28 @@ class Index < Test::View end end + it "allows to specify slim template engine" do + within_application_directory do + subject.call(name: "special.users.index", template: "slim") + + template_file = <<~EXPECTED + h1 Test::Views::Special::Users::Index + EXPECTED + expect(fs.read("app/templates/special/users/index.html.slim")).to eq(template_file) + end + end + + it "allows to specify HAML template engine" do + within_application_directory do + subject.call(name: "special.users.index", template: "haml") + + template_file = <<~EXPECTED + %h1 Test::Views::Special::Users::Index + EXPECTED + expect(fs.read("app/templates/special/users/index.html.haml")).to eq(template_file) + end + end + context "with existing file" do before do within_application_directory do @@ -143,6 +165,29 @@ class Index < Main::View expect(output).to include("Created slices/main/templates/users/index.html.erb") end end + it "allows to specify slim template engine" do + within_application_directory do + fs.mkdir("slices/main") + subject.call(name: "users.index", slice: "main", template: "slim") + + template_file = <<~EXPECTED + h1 Main::Views::Users::Index + EXPECTED + expect(fs.read("slices/main/templates/users/index.html.slim")).to eq(template_file) + end + end + + it "allows to specify HAML template engine" do + within_application_directory do + fs.mkdir("slices/main") + subject.call(name: "users.index", slice: "main", template: "haml") + + template_file = <<~EXPECTED + %h1 Main::Views::Users::Index + EXPECTED + expect(fs.read("slices/main/templates/users/index.html.haml")).to eq(template_file) + end + end context "with existing file" do before do