middleman-bem-html 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 26e4c5bb74924edf2372c094c3ef63ee6e72c1ce
4
+ data.tar.gz: 44c17a39685b5762bd5b828c9a7f28dcca516d1b
5
+ SHA512:
6
+ metadata.gz: 5dfe42cf4b92df86d33bedca54fc3240376c119b8514633a036580c15e6e9788a3a00d7c1f3e650c3cdf894e5744355cbad6e10a46f0596e2e4c1fdf23e89e7c
7
+ data.tar.gz: 3b0504febac3530765572cb1a215e58c81e125ccc6a2cf4b5901d52cd1b18858eaa74cd95b3f34de5a39d2c92e1cd6d22c027c554a65aee93584404cce4f142f
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+
3
+ # Ignore bundler lock file
4
+ /Gemfile.lock
5
+
6
+ # Ignore pkg folder
7
+ /pkg
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ # If you do not have OpenSSL installed, update
2
+ # the following line to use "http://" instead
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in bem_html.gemspec
6
+ gemspec
7
+
8
+ group :development do
9
+ gem 'rake'
10
+ gem 'rdoc'
11
+ gem 'yard'
12
+ end
13
+
14
+ group :test do
15
+ gem 'cucumber'
16
+ gem 'aruba'
17
+ gem 'rspec'
18
+ end
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'cucumber/rake/task'
5
+
6
+ Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t|
7
+ t.cucumber_opts = '--color --tags ~@wip --strict'
8
+ end
9
+
10
+ require 'rake/clean'
11
+
12
+ task test: ['cucumber']
13
+
14
+ task default: :test
data/Readme.md ADDED
@@ -0,0 +1,82 @@
1
+ # middleman-bem-html
2
+
3
+ A Middleman extension to add BEM classes to HTML based on HTML attributes.
4
+
5
+ Makes use of [bem_html](https://github.com/oncomouse/bem_html) to handle class generation and [css_dead_class](https://github.com/oncomouse/css_dead_class) to cleanup unused CSS classes.
6
+
7
+ ## Purpose
8
+
9
+ In large projects, BEM namespacing can get fairly complicated. In Sass and PostCSS, there exist a number of helper methods to simply the creation of nested Block, Element, Modifier classes; however, this plugin provides similar helper methods within HTML itself.
10
+
11
+ ## Sample Usage
12
+
13
+ Say you had a BEM block called "widget" that had the following structure in HTML:
14
+
15
+ ~~~html
16
+
17
+ <div class="widget">
18
+ <h1 class="widget__heading widget__heading--lime">Heading</h1>
19
+ <section class="widget__content">
20
+ <p class="widget__content__first-paragraph">First Paragraph</p>
21
+ </section>
22
+ </div>
23
+ ~~~
24
+
25
+ With bem-html, you could define that structure instead as the following:
26
+
27
+ ~~~html
28
+ <div bem-block="widget">
29
+ <h1 bem-element="heading" modifiers="[:lime]">Heading</h1>
30
+ <section bem-element="content">
31
+ <p bem-element="first-paragraph">First Paragraph</p>
32
+ </section>
33
+ </div>
34
+ ~~~
35
+
36
+ And this extension would produce the desired HTML.
37
+
38
+ Originally, this extension was specifically designed for HAML, where it really shines:
39
+
40
+ ~~~haml
41
+ %div{bem:{block: :widget}}
42
+ %h1{bem:{element: :heading, modifiers: [:lime]}} Heading
43
+ %section{bem:{element: :content}}
44
+ %p{bem: {element: "first-paragraph"}} First Paragraph
45
+ ~~~
46
+
47
+ ## Installation
48
+
49
+ Add
50
+
51
+ ~~~
52
+ gem "middleman-bem-html"
53
+ ~~~
54
+
55
+ to your `Gemfile` and run `bundle update`
56
+
57
+ ## Configuration
58
+
59
+ In `config.rb`, add the following:
60
+
61
+ ~~~ruby
62
+ activate :bem_html
63
+
64
+ config[:classes_to_keep] = [
65
+ 'no-js',
66
+ ]
67
+ config[:internal_css] = true
68
+ ~~~
69
+
70
+ The two configuration options are:
71
+
72
+ ### `:classes_to_keep`
73
+
74
+ An array of CSS class names to not remove, even if they are not present in any of the CSS files.
75
+
76
+ ### `:internal_css`
77
+
78
+ **defaults to `true`**
79
+
80
+ If you are using any `external_pipeline` calls to configure your CSS files (like gulp or PostCSS), the `after_build` method that this extension uses to remove all the unused CSS from production HTML will run before the CSS has been generated (as `external_pipeline` calls always run *after* extension methods), as such you *must* use an `external_pipeline` to remove the unused CSS classes this extension may generate.
81
+
82
+ If this effects you, please consider using [postcss-deadclass](https://github.com/oncomouse/postcss-deadclass) to remove the unused CSS classes using PostCSS.
@@ -0,0 +1,4 @@
1
+ PROJECT_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__)))
2
+ require 'middleman-core'
3
+ require 'middleman-core/step_definitions'
4
+ require File.join(PROJECT_ROOT_PATH, 'lib', 'bem_html')
@@ -0,0 +1,112 @@
1
+ require 'active_support/core_ext/object/try'
2
+ require 'memoist'
3
+ require 'middleman-core/contracts'
4
+ require 'css_dead_class'
5
+ require 'bem_html'
6
+
7
+ class ::Middleman::Extension::BemHtml < ::Middleman::Extension
8
+ option :ignore, [], 'Patterns to avoid minifying'
9
+ option :inline_content_types, %w(text/html text/php), 'Content types of resources that contain bem commands'
10
+
11
+ def initialize(app, options_hash={}, &block)
12
+ super
13
+ end
14
+
15
+ def ready
16
+ # Setup Rack middleware to minify CSS
17
+ app.use Rack, compressor: options[:compressor],
18
+ ignore: Array(options[:ignore]) + [/\.min\./],
19
+ inline_content_types: options[:inline_content_types]
20
+ end
21
+
22
+ def after_build
23
+ # This will work if you are building your CSS files in Middleman. If you are using an external_pipeline,
24
+ # this after_build method will trigger before the external_pipeline. As such, you need to use PostCSS
25
+ # and http://github.com/oncomouse/postcss-deadclass to remove all the cruft.
26
+
27
+ # Set config[:internal_css] to false if you are using an external_pipeline and postcss-deadclass
28
+ runInternalDeCrufter = app.config.internal_css || true
29
+ if runInternalDeCrufter
30
+ classesToKeep = app.config.classes_to_keep || []
31
+ cssFiles = Dir.glob("#{app.config.build_dir}/#{app.config.css_dir}/**/*.css")
32
+ htmlFiles = Dir.glob("#{app.config.build_dir}/**/*.html")
33
+
34
+ css_deadfiles = CSSDeadClass.new({
35
+ html_files: htmlFiles,
36
+ css_files: cssFiles,
37
+ classes_to_keep: classesToKeep
38
+ })
39
+ css_deadfiles.parse
40
+ end
41
+ end
42
+
43
+ class Rack
44
+ extend Memoist
45
+ include Contracts
46
+
47
+ # Init
48
+ # @param [Class] app
49
+ # @param [Hash] options
50
+ Contract RespondTo[:call], {
51
+ ignore: ArrayOf[PATH_MATCHER]
52
+ } => Any
53
+ def initialize(app, options={})
54
+ @app = app
55
+ @ignore = options.fetch(:ignore)
56
+ @inline_content_types = options[:inline_content_types]
57
+ end
58
+
59
+ # Rack interface
60
+ # @param [Rack::Environmemt] env
61
+ # @return [Array]
62
+ def call(env)
63
+ status, headers, response = @app.call(env)
64
+
65
+ content_type = headers['Content-Type'].try(:slice, /^[^;]*/)
66
+ path = env['PATH_INFO']
67
+
68
+ minified = if minifiable_inline?(content_type)
69
+ minify_inline(::Middleman::Util.extract_response_text(response))
70
+ end
71
+
72
+ if minified
73
+ headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s
74
+ response = [minified]
75
+ end
76
+
77
+ [status, headers, response]
78
+ end
79
+
80
+ private
81
+
82
+ # Whether the path should be ignored
83
+ # @param [String] path
84
+ # @return [Boolean]
85
+ def ignore?(path)
86
+ @ignore.any? { |ignore| ::Middleman::Util.path_match(ignore, path) }
87
+ end
88
+ memoize :ignore?
89
+
90
+ # Whether this type of content contains inline content that can be minified
91
+ # @param [String, nil] content_type
92
+ # @return [Boolean]
93
+ def minifiable_inline?(content_type)
94
+ @inline_content_types.include?(content_type)
95
+ end
96
+ memoize :minifiable_inline?
97
+
98
+ # Detect and minify inline content
99
+ # @param [String] content
100
+ # @return [String]
101
+ def minify_inline(content)
102
+ BemHtml.parse(content)
103
+ end
104
+ memoize :minify_inline
105
+ end
106
+ end
107
+
108
+
109
+ Middleman::Extensions.register :bem_html do
110
+ #require "bem_html/extension"
111
+ ::Middleman::Extension::BemHtml
112
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "middleman-bem-html"
6
+ s.version = "1.0.1"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Andrew Pilsch"]
9
+ s.email = ["apilsch@tamu.edu"]
10
+ s.homepage = "http://github.com/oncomouse/middleman-bem-html"
11
+ s.summary = %q{Middleman extension to use bem_html and css_dead_class to add BEM class tags to HTML objects that have attributes (bem-block, bem-element, bem-modifiers).}
12
+ # s.description = %q{A longer description of your extension}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ # The version of middleman-core your extension depends on
20
+ s.add_runtime_dependency("middleman-core", ["~> 4"])
21
+ s.add_runtime_dependency("bem_html", ["~> 1"])
22
+ s.add_runtime_dependency("css_dead_class", ["~> 1"])
23
+
24
+ s.license = "ISC"
25
+
26
+ # Additional dependencies
27
+ # s.add_runtime_dependency("gem-name", "gem-version")
28
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-bem-html
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Pilsch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: middleman-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bem_html
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: css_dead_class
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1'
55
+ description:
56
+ email:
57
+ - apilsch@tamu.edu
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - Rakefile
65
+ - Readme.md
66
+ - features/support/env.rb
67
+ - lib/middleman-bem-html.rb
68
+ - middleman-bem-html.gemspec
69
+ homepage: http://github.com/oncomouse/middleman-bem-html
70
+ licenses:
71
+ - ISC
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.5.1
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Middleman extension to use bem_html and css_dead_class to add BEM class tags
93
+ to HTML objects that have attributes (bem-block, bem-element, bem-modifiers).
94
+ test_files:
95
+ - features/support/env.rb