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 +7 -0
- data/.gitignore +7 -0
- data/Gemfile +18 -0
- data/Rakefile +14 -0
- data/Readme.md +82 -0
- data/features/support/env.rb +4 -0
- data/lib/middleman-bem-html.rb +112 -0
- data/middleman-bem-html.gemspec +28 -0
- metadata +95 -0
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
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,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
|