middleman-bem-html 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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