diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0ad438d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +; top-most EditorConfig file +root = true + +; Unix-style newlines +[*] +end_of_line = LF +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/CHANGELOG.md b/CHANGELOG.md index 89a9e56..cebd21c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Upcoming release +**Enhancements:** + +- Implement a styleguide view + ## v2.1.0 (2018-05-31) **Enhancements:** diff --git a/README.md b/README.md index 377f6c1..092daac 100644 --- a/README.md +++ b/README.md @@ -313,6 +313,23 @@ I18n.available_locales = [:en, :fr] > If you have the `rails-i18n` gem in your `Gemfile`, you should whitelist locales to prevent creating a lot of > locale files when you generate a new component. +### Styleguide + +Update your routes to mount the Komponent engine. + +```ruby +# config/routes.rb +Rails.application.routes.draw do + mount Komponent::Engine => "/" if Rails.env.development? + + # ... +end +``` + +Then you need to update the `_example.html.slim` file you have inside your components. This file is used to render the examples. + +Finally just visit to `http://localhost:3000/styleguide`. + ### Configuration #### Change default root path diff --git a/app/controllers/komponent/styleguide_controller.rb b/app/controllers/komponent/styleguide_controller.rb new file mode 100644 index 0000000..58ad027 --- /dev/null +++ b/app/controllers/komponent/styleguide_controller.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require "komponent/component" + +module Komponent + class StyleguideController < ::ApplicationController + layout 'komponent' + rescue_from ActionView::MissingTemplate, with: :missing_template + + def index; end + + def show + @component = Komponent::Component.find(params[:id]) + end + + private + + def missing_template + render "komponent/styleguide/missing_template" + end + end +end diff --git a/app/views/komponent/styleguide/index.html.erb b/app/views/komponent/styleguide/index.html.erb new file mode 100644 index 0000000..aff5aa1 --- /dev/null +++ b/app/views/komponent/styleguide/index.html.erb @@ -0,0 +1,15 @@ +
+

Styleguide

+
+ +<% if komponent_components.any? %> +
+ Select one of the components from the side to view its examples and documentation. +
+<% else %> +
+

Hint:You haven't created any components yet

+

You can generate your first component by running:

+
rails generate component component-name
+
+<% end %> diff --git a/app/views/komponent/styleguide/missing_template.html.erb b/app/views/komponent/styleguide/missing_template.html.erb new file mode 100644 index 0000000..6fa0d09 --- /dev/null +++ b/app/views/komponent/styleguide/missing_template.html.erb @@ -0,0 +1,3 @@ +

Example missing

+ +

Please create <%= @component.path %>/_example.html.<%= Rails.application.config.app_generators.rails[:template_engine] || :erb %> file.

diff --git a/app/views/komponent/styleguide/show.html.erb b/app/views/komponent/styleguide/show.html.erb new file mode 100644 index 0000000..af5083e --- /dev/null +++ b/app/views/komponent/styleguide/show.html.erb @@ -0,0 +1 @@ +<%= render partial: @component.example_view %> diff --git a/app/views/layouts/komponent.html.erb b/app/views/layouts/komponent.html.erb new file mode 100644 index 0000000..9fdaec4 --- /dev/null +++ b/app/views/layouts/komponent.html.erb @@ -0,0 +1,17 @@ + + + + Styleguide + <%= javascript_pack_tag "komponent" %> + <%= stylesheet_pack_tag "komponent", media: "all" %> + <%= csrf_meta_tags %> + + + <%=c 'komponent/header' %> + <%=c 'komponent/sidebar' %> + <%=c 'komponent/container' do %> + <%= yield %> + <% end %> + <%=c 'komponent/footer' %> + + diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..e63dcaf --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Komponent::Engine.routes.draw do + resources :styleguide, only: %i[index show] #, path: Komponent.configuration.styleguide_path +end diff --git a/features/component_generator.feature b/features/component_generator.feature index e9541bf..113a3ae 100644 --- a/features/component_generator.feature +++ b/features/component_generator.feature @@ -11,6 +11,7 @@ Feature: Component generator | awesome_button/awesome_button.css | | awesome_button/awesome_button.js | | awesome_button/awesome_button_component.rb | + | awesome_button/_example.html.erb | And the file named "index.js" should contain: """ import "components/awesome_button/awesome_button"; @@ -30,6 +31,7 @@ Feature: Component generator | admin/sub_admin/awesome_button/admin_sub_admin_awesome_button.css | | admin/sub_admin/awesome_button/admin_sub_admin_awesome_button.js | | admin/sub_admin/awesome_button/admin_sub_admin_awesome_button_component.rb | + | admin/sub_admin/awesome_button/_example.html.erb | And the file named "index.js" should contain: """ import "components/admin"; @@ -84,6 +86,7 @@ Feature: Component generator When I run `rails generate component AwesomeButton` And I cd to "frontend/components/awesome_button" Then a file named "_awesome_button.html.erb" should exist + And a file named "_example.html.erb" should exist Scenario: Generate component with custom template engine defined to `haml` Given a file named "config/initializers/custom_configuration.rb" with: @@ -93,6 +96,7 @@ Feature: Component generator When I run `rails generate component AwesomeButton` And I cd to "frontend/components/awesome_button" Then a file named "_awesome_button.html.haml" should exist + And a file named "_example.html.haml" should exist Scenario: Generate component with custom template engine defined to `slim` Given a file named "config/initializers/custom_configuration.rb" with: @@ -102,6 +106,7 @@ Feature: Component generator When I run `rails generate component AwesomeButton` And I cd to "frontend/components/awesome_button" Then a file named "_awesome_button.html.slim" should exist + And a file named "_example.html.slim" should exist Scenario: Generate component with custom stylesheet engine defined to `scss` Given a file named "config/initializers/custom_configuration.rb" with: diff --git a/frontend/components/komponent/container/_komponent_container.html.erb b/frontend/components/komponent/container/_komponent_container.html.erb new file mode 100644 index 0000000..31dc85d --- /dev/null +++ b/frontend/components/komponent/container/_komponent_container.html.erb @@ -0,0 +1,3 @@ +
+ <%= yield %> +
diff --git a/frontend/components/komponent/container/komponent_container.css b/frontend/components/komponent/container/komponent_container.css new file mode 100644 index 0000000..c020b26 --- /dev/null +++ b/frontend/components/komponent/container/komponent_container.css @@ -0,0 +1,4 @@ +.komponent-container { + margin-left: 24rem; + margin-top: 4rem; +} diff --git a/frontend/components/komponent/container/komponent_container.js b/frontend/components/komponent/container/komponent_container.js new file mode 100644 index 0000000..70b1a82 --- /dev/null +++ b/frontend/components/komponent/container/komponent_container.js @@ -0,0 +1 @@ +import "./komponent_container.css"; diff --git a/frontend/components/komponent/container/komponent_container_component.rb b/frontend/components/komponent/container/komponent_container_component.rb new file mode 100644 index 0000000..3a2362d --- /dev/null +++ b/frontend/components/komponent/container/komponent_container_component.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module KomponentContainerComponent + extend ComponentHelper +end diff --git a/frontend/components/komponent/footer/_komponent_footer.html.erb b/frontend/components/komponent/footer/_komponent_footer.html.erb new file mode 100644 index 0000000..c3a1fae --- /dev/null +++ b/frontend/components/komponent/footer/_komponent_footer.html.erb @@ -0,0 +1,3 @@ + diff --git a/frontend/components/komponent/footer/komponent_footer.css b/frontend/components/komponent/footer/komponent_footer.css new file mode 100644 index 0000000..60555fc --- /dev/null +++ b/frontend/components/komponent/footer/komponent_footer.css @@ -0,0 +1,21 @@ +.komponent-footer { + font-size: 1.4rem; + position: absolute; + bottom: 4rem; + right: 4rem; + text-align: center; + + &, + a { + color: #999; + } + + a { + text-decoration: none; + + &:hover, + &:focus { + color: #0038ea; + } + } +} diff --git a/frontend/components/komponent/footer/komponent_footer.js b/frontend/components/komponent/footer/komponent_footer.js new file mode 100644 index 0000000..c1d61e6 --- /dev/null +++ b/frontend/components/komponent/footer/komponent_footer.js @@ -0,0 +1 @@ +import "./komponent_footer.css"; diff --git a/frontend/components/komponent/footer/komponent_footer_component.rb b/frontend/components/komponent/footer/komponent_footer_component.rb new file mode 100644 index 0000000..9f64ef8 --- /dev/null +++ b/frontend/components/komponent/footer/komponent_footer_component.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module KomponentFooterComponent + extend ComponentHelper +end diff --git a/frontend/components/komponent/header/_komponent_header.html.erb b/frontend/components/komponent/header/_komponent_header.html.erb new file mode 100644 index 0000000..e4feb12 --- /dev/null +++ b/frontend/components/komponent/header/_komponent_header.html.erb @@ -0,0 +1,3 @@ +
+ +
diff --git a/frontend/components/komponent/header/komponent_header.css b/frontend/components/komponent/header/komponent_header.css new file mode 100644 index 0000000..6d0e637 --- /dev/null +++ b/frontend/components/komponent/header/komponent_header.css @@ -0,0 +1,9 @@ +.komponent-header { + align-items: center; + background-color: #0038ea; + color: white; + display: flex; + font-size: 1.8rem; + height: 8rem; + padding: 2rem; +} diff --git a/frontend/components/komponent/header/komponent_header.js b/frontend/components/komponent/header/komponent_header.js new file mode 100644 index 0000000..b013393 --- /dev/null +++ b/frontend/components/komponent/header/komponent_header.js @@ -0,0 +1 @@ +import "./komponent_header.css"; diff --git a/frontend/components/komponent/header/komponent_header_component.rb b/frontend/components/komponent/header/komponent_header_component.rb new file mode 100644 index 0000000..7d3d6b6 --- /dev/null +++ b/frontend/components/komponent/header/komponent_header_component.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module KomponentHeaderComponent + extend ComponentHelper +end diff --git a/frontend/components/komponent/index.js b/frontend/components/komponent/index.js new file mode 100644 index 0000000..878e312 --- /dev/null +++ b/frontend/components/komponent/index.js @@ -0,0 +1,4 @@ +import "components/komponent/container/komponent_container"; +import "components/komponent/footer/komponent_footer"; +import "components/komponent/header/komponent_header"; +import "components/komponent/sidebar/komponent_sidebar"; diff --git a/frontend/components/komponent/sidebar/_komponent_sidebar.html.erb b/frontend/components/komponent/sidebar/_komponent_sidebar.html.erb new file mode 100644 index 0000000..0979f30 --- /dev/null +++ b/frontend/components/komponent/sidebar/_komponent_sidebar.html.erb @@ -0,0 +1,10 @@ +
+
Components
+ +
diff --git a/frontend/components/komponent/sidebar/komponent_sidebar.css b/frontend/components/komponent/sidebar/komponent_sidebar.css new file mode 100644 index 0000000..c4d308a --- /dev/null +++ b/frontend/components/komponent/sidebar/komponent_sidebar.css @@ -0,0 +1,35 @@ +.komponent-sidebar { + background-color: #dbe1f3; + bottom: 0; + left: 0; + padding: 4rem 2rem; + position: absolute; + top: 8rem; + width: 20rem; + + &-title { + color: #0038ea; + font-size: 1.4rem; + font-weight: bold; + letter-spacing: 0.2rem; + margin: 0 0 2rem; + text-transform: uppercase; + } + + &-items { + line-height: 1.25; + list-style: none; + margin: 0; + padding: 0; + } + + &-item + &-item { + margin-top: 0.5rem; + } + + a { + color: #333; + display: block; + text-decoration: none; + } +} diff --git a/frontend/components/komponent/sidebar/komponent_sidebar.js b/frontend/components/komponent/sidebar/komponent_sidebar.js new file mode 100644 index 0000000..2b3af41 --- /dev/null +++ b/frontend/components/komponent/sidebar/komponent_sidebar.js @@ -0,0 +1 @@ +import "./komponent_sidebar.css"; diff --git a/frontend/components/komponent/sidebar/komponent_sidebar_component.rb b/frontend/components/komponent/sidebar/komponent_sidebar_component.rb new file mode 100644 index 0000000..3395063 --- /dev/null +++ b/frontend/components/komponent/sidebar/komponent_sidebar_component.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module KomponentSidebarComponent + extend ComponentHelper +end diff --git a/lib/generators/component/component_generator.rb b/lib/generators/component/component_generator.rb index e419cf1..add4aa7 100644 --- a/lib/generators/component/component_generator.rb +++ b/lib/generators/component/component_generator.rb @@ -34,6 +34,10 @@ def create_locale_files end end + def create_example_view_file + template "#{template_prefix}example.html.#{template_engine}.erb", component_path + "_example.html.#{template_engine}" + end + def import_to_packs root_path = default_path base_path = root_path + "components" diff --git a/lib/generators/component/templates/example.html.erb.erb b/lib/generators/component/templates/example.html.erb.erb new file mode 100644 index 0000000..bbedc2a --- /dev/null +++ b/lib/generators/component/templates/example.html.erb.erb @@ -0,0 +1,3 @@ +

<%= component_name %>

+ +<%%= component "<%= component_name %>" %> diff --git a/lib/generators/component/templates/example.html.haml.erb b/lib/generators/component/templates/example.html.haml.erb new file mode 100644 index 0000000..e3f98fa --- /dev/null +++ b/lib/generators/component/templates/example.html.haml.erb @@ -0,0 +1,3 @@ +%h1 <%= component_name %> + += component "<%= component_name %>" diff --git a/lib/generators/component/templates/example.html.slim.erb b/lib/generators/component/templates/example.html.slim.erb new file mode 100644 index 0000000..ed536ad --- /dev/null +++ b/lib/generators/component/templates/example.html.slim.erb @@ -0,0 +1,3 @@ +h1 <%= component_name %> + += component "<%= component_name %>" diff --git a/lib/komponent.rb b/lib/komponent.rb index 3d737e6..965007c 100644 --- a/lib/komponent.rb +++ b/lib/komponent.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require "komponent/version" +require 'komponent/version' module Komponent - require 'komponent/railtie' if defined?(Rails) + require 'komponent/engine' if defined?(Rails) end diff --git a/lib/komponent/component.rb b/lib/komponent/component.rb new file mode 100644 index 0000000..3c988fe --- /dev/null +++ b/lib/komponent/component.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module Komponent + class Component + class << self + def all + component_dirs = components_root.join('*/**/') + + components = {} + + # TODO: list only components directories + # use ComponentPathResolver? + Dir.glob(component_dirs).sort.each do |component_dir| + component_path = Pathname.new(component_dir).relative_path_from(components_root).to_s + + next unless File.exist?(components_root.join(component_path) + .join("#{File.basename(component_path)}_component.rb")) + + components[component_path] = Component.new(component_path) + end + + components + end + + def find(id) + components = all + + raise Exception, "Component with ID=#{id} not found" unless components.keys.include? id + components.fetch(id) + end + + def components_root + @components_root ||= Rails.application.config.komponent.root.join('components') + end + end + + attr_reader :id + + def initialize(id) + @id = id + end + + def title + id.titleize + end + + def path + Komponent::ComponentPathResolver.new.resolve(@id) + end + + def example_view + "components/#{id}/example" + end + end +end diff --git a/lib/komponent/railtie.rb b/lib/komponent/engine.rb similarity index 64% rename from lib/komponent/railtie.rb rename to lib/komponent/engine.rb index 283e750..f971744 100644 --- a/lib/komponent/railtie.rb +++ b/lib/komponent/engine.rb @@ -7,7 +7,9 @@ require 'komponent/translation' module Komponent - class Railtie < Rails::Railtie + class Engine < Rails::Engine + isolate_namespace Komponent + config.komponent = ActiveSupport::OrderedOptions.new config.komponent.root = nil config.komponent.component_paths = [] @@ -22,6 +24,9 @@ class Railtie < Rails::Railtie app.config.komponent.component_paths.prepend( app.config.komponent.root.join("components") ) + app.config.komponent.component_paths.append( + Komponent::Engine.root.join('frontend/components') + ) ActiveSupport.on_load :action_view do require 'komponent/komponent_helper' @@ -34,5 +39,15 @@ class Railtie < Rails::Railtie ) end end + + initializer "my_engine.action_dispatch" do |app| + ActiveSupport.on_load :action_controller do + ActionController::Base.prepend_view_path Komponent::Engine.root.join("frontend") + end + end + + initializer 'komponent.autoload', before: :set_autoload_paths do |app| + app.config.autoload_paths << Komponent::Engine.root.join('frontend') + end end end diff --git a/lib/komponent/komponent_helper.rb b/lib/komponent/komponent_helper.rb index fb90302..a7c53a4 100644 --- a/lib/komponent/komponent_helper.rb +++ b/lib/komponent/komponent_helper.rb @@ -13,4 +13,8 @@ def component(component_name, locals = {}, options = {}, &block) ) end alias :c :component + + def komponent_components + Komponent::Component.all + end end