grouped_property_scss_linter 1.1.3

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: e22237fdcbef363b71f89896640289081051eeff
4
+ data.tar.gz: 0056fd882b1a9b93488294289b4dfa5b2c21d90e
5
+ SHA512:
6
+ metadata.gz: cfece3ebdca1ca05691671646bb7530c1fc2733674911c1f63aae367688fcceba950fa14a626c780575874a35ae66f625e54971111f87e32c1e8c7c4a3d6f1fa
7
+ data.tar.gz: bbf00eaf2b8a150e0da8c9db5d3661274f54c94eef766e3cef375f637d792ea72a8e9cc3f97893fd4417063c721e5fc5ea521339d8f3735cb17bb86efe7b72a3
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.scss-lint.yml ADDED
@@ -0,0 +1,17 @@
1
+ linters:
2
+ GroupedPropertyOrder:
3
+ enabled: true
4
+
5
+ # defaults: applied to all groups
6
+ defaults:
7
+ space_around: true
8
+ max_no_space: 3
9
+
10
+ # preferred style
11
+ style: grouped-smacss
12
+
13
+ # or a definition of your own. Note that this takes precedence over style
14
+ groups:
15
+
16
+ # whether you get extended hinting information in the output
17
+ extended_hinting: false
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grouped_property_scss_linter.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016–2017 Jon Pearse
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,181 @@
1
+ h1. Grouped Property Linter for SCSS-Lint
2
+
3
+ This is a plugin linter for "SCSS-Lint":https://github.com/brigade/scss-lint that provides a saner alternative to the built-in @PropertySortOrder@ linter.
4
+
5
+ Instead of requiring properties to be arranged in a strict order, it instead allows groups of properties (eg: @top@, @right@, @bottom@ & @left@) to be defined, and then lints the order of the _groups_ in your SASS.
6
+ As long as properties are grouped correctly, the order of individual properties is unimportant.
7
+
8
+ h2. Examples
9
+
10
+ Using the default configuration:
11
+
12
+ *Bad*
13
+
14
+ <pre><code lang="css">.selector {
15
+ padding: .625rem;
16
+
17
+ text-decoration: underline;
18
+ font-size: 1rem;
19
+ line-height: 1.3;
20
+ font-weight: bold;
21
+ color: rgba(20, 20, 20, .8);
22
+
23
+ display: inline-block;
24
+ background: #F00;
25
+ }</code></pre>
26
+
27
+ *Good*
28
+
29
+ <pre><code lang="css">.selector {
30
+ display: inline-block;
31
+ padding: .625rem;
32
+
33
+ color: rgba(20, 20, 20, .8);
34
+ background: #F00;
35
+
36
+ font-size: 1rem;
37
+ line-height: 1.3em;
38
+ font-weight: bold;
39
+ text-decoration: underline;
40
+ }</code></pre>
41
+
42
+ Because the order of individual properties within a group is ignored, neither of the selectors below would generate a warning.
43
+
44
+ <pre><code lang="css">.selector-one {
45
+ display: block;
46
+
47
+ height: 10em;
48
+ width: 90%;
49
+ }
50
+
51
+ .selector-two {
52
+ display: block;
53
+
54
+ width: 90%;
55
+ height: 10em;
56
+ }</code></pre>
57
+
58
+ h2. Usage
59
+
60
+ In order to use this linter, you’ll need to modify both your Gemfile and scss-lint configuration file (typically @.scss-lint@).
61
+
62
+ *Gemfile*
63
+
64
+ <pre><code lang="ruby">gem 'grouped_property_scss_linter'</code></pre>
65
+
66
+ *SCSS-Lint configuration file*
67
+
68
+ You will need to add @grouped_property_scss_linter@ to the @plugin_gems@ variable:
69
+
70
+ <pre><code lang="yaml">plugin_gems: ['grouped_property_scss_linter']</code></pre>
71
+
72
+ h2. Configuration
73
+
74
+ When included, this linter is enabled by default, and enforces a modified version of "SMACSS’s categories":https://smacss.com/book/categorizing
75
+
76
+ The configuration may be altered in the same way as other linters, by adding a section to your SCSS-Lint configuration file.
77
+
78
+ <pre><code lang="yaml">linters:
79
+ GroupedPropertyOrder:
80
+ enabled: true
81
+ defaults:
82
+ space_around: true
83
+ max_no_space: 3
84
+ style: smacss
85
+ groups:
86
+ </code></pre>
87
+
88
+ h3. Options
89
+
90
+ - @enabled@ _(boolean)_ := switches the module on and off (default: on)
91
+ - @defaults@ _(hash)_ := default linting settings that are applied to all groups (can be overridden per-group)
92
+ - @style@ _(string, optional)_ := the name of a preconfigured style (see below, defaults to @grouped-smacss@)
93
+ - @groups@ _(hash, optional)_ := a hash of configured groups. Note that specifying anything here will override the @style@ option
94
+ - @extended_hinting@ _(boolean, optional)_ := enables additional group information in hinting output (default @false@)
95
+
96
+ h4. Default options
97
+
98
+ - @space_around@ _(boolean)_ := whether to require space around individual groups (default: true)
99
+ - @max_no_space@ _(int)_ := the maximum number of properties that can be specified in a group before space is required around it (default: 3, ignored if @space_around@ is @false@)
100
+
101
+ h4. Predefined styles
102
+
103
+ There a number of property orders/styles supplied with the gem. These are:
104
+
105
+ - @smacss@ := an implementation of "SMACSS":https://smacss.com/book/formatting
106
+ - @grouped-smacss@ _(default)_ := a tweaked version of SMACSS with slightly more granular grouping
107
+ - @concentric@ := an implementation of "Concentric CSS":https://github.com/brandon-rhodes/Concentric-CSS
108
+ - @personal@ := my personal ordering, just cuz…
109
+
110
+
111
+ h3. Specifying your own configuration
112
+
113
+ Groups are specified as a YAML hash, in the order in which they should appear in your SASS. Each group *must* have a @properties@ member, containing an array of properties that may appear in this group.
114
+
115
+ <pre><code lang="yaml">groups:
116
+ tables:
117
+ properties:
118
+ - table-layout
119
+ - border-collapse
120
+ - empty-cells</code></pre>
121
+
122
+ Specifies a group called @tables@, which may contain @table-layout@, @border-collapse@ and @empty-cells@ properties.
123
+
124
+ h4. Wildcard properties
125
+
126
+ In cases where a number of properties may have the same prefix, wildcard properties may used instead.
127
+ Thus, the following group definitions are equivalent.
128
+
129
+ <pre><code lang="yaml">groups:
130
+ text:
131
+ properties:
132
+ - font
133
+ - font-size
134
+ - font-family
135
+ - font-style
136
+ text_two:
137
+ properties:
138
+ - font*</code></pre>
139
+
140
+ Naturally, you might want to use this functionality carefully…
141
+
142
+ h4. Overriding defaults
143
+
144
+ In some cases, you may wish to override the default linting options. This can be done by adding the appropriate option to the group hash:
145
+
146
+ <pre><code lang="yaml">groups:
147
+ tables:
148
+ max_no_space: 1
149
+ properties:
150
+ - table-layout
151
+ - border-collapse
152
+ - empty-cells</code></pre>
153
+
154
+ This defines a @tables@ group as earlier, but requires a space around it at all times.
155
+
156
+ h2. Why?
157
+
158
+ I’ve written a "blog post":https://jonpearse.net/articles/2016/07/on-linting-and-bringing-order-to-sass about this, but the short version is that I really don’t get on with SCSS-Lint’s default @PropertySortOrder@ linter =)
159
+
160
+ h2. Version History
161
+
162
+ h3. 1.1.2 _(March 18th, 2017)_
163
+
164
+ * eventually pushing this up to RubyGems
165
+
166
+ h3. 1.1.1 _(July 15th, 2016)_
167
+
168
+ * fixing dumb typoes in the readme
169
+
170
+ h3. 1.1.0 _(July 15th, 2016)_
171
+
172
+ * improved hint messages to be somewhat more useful to the average developer
173
+
174
+ h3. 1.0.0 _(June 12th, 2016)_
175
+
176
+ * initial release
177
+
178
+ h2. Mandatory sales pitch
179
+
180
+ When I’m not hacking at random things, I’m a freelance web developer specialising in all things front-end, based in the beautiful city of Cardiff, UK.
181
+ I’m usually kept fairly busy with project work, but I’m always on the lookout for new people to do cool stuff with. "Drop me a line":mailto:hello@jonpearse.net – I’d love to hear from you!
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,82 @@
1
+ # Concentric CSS [ http://rhodesmill.org/brandon/2011/concentric-css/ ]
2
+ #
3
+ # This is roughly based on SCSS-Lint‘s specification, found at
4
+ # [ https://github.com/brigade/scss-lint/blob/master/data/property-sort-orders/concentric.txt ]
5
+ groups:
6
+ directions:
7
+ - display
8
+ - position
9
+ - top
10
+ - right
11
+ - bottom
12
+ - left
13
+
14
+ columns:
15
+ - columns
16
+ - column*
17
+
18
+ float:
19
+ - float
20
+ - clear
21
+
22
+ transform:
23
+ - transform*
24
+ - transition
25
+ - animation*
26
+
27
+ visibility:
28
+ - visibility
29
+ - opacity
30
+ - z-index
31
+
32
+ box:
33
+ - margin*
34
+ - outline
35
+ - border
36
+ - border-style
37
+ - border-color
38
+ - border-radius
39
+ - border-width
40
+ - border-image
41
+ - border-top*
42
+ - border-right*
43
+ - border-bottom*
44
+ - border-left*
45
+ - box-shadow
46
+ - background*
47
+ - cursor
48
+ - padding*
49
+
50
+ dimensions:
51
+ - width
52
+ - min-width
53
+ - max-width
54
+ - height
55
+ - min-height
56
+ - max-height
57
+ - overflow*
58
+
59
+ lists:
60
+ - list-style*
61
+
62
+ tables:
63
+ - caption-side
64
+ - table-layout
65
+ - border-collapse
66
+ - border-spacing
67
+ - empty-cells
68
+
69
+ content:
70
+ - vertical-align
71
+ - text*
72
+ - line-height
73
+ - word-spacing
74
+ - letter-spacing
75
+ - white-space
76
+ - color
77
+ - font*
78
+
79
+ generated:
80
+ - content
81
+ - quotes
82
+ - counter* # it strikes me that this should be in lists, but it’s generated, so…
@@ -0,0 +1,151 @@
1
+ # This is a variation on SMACSS that specifies a more granular grouping of properties, rather than the five Jonathan
2
+ # Snook proposes. YMMV =)
3
+ groups:
4
+ box-position:
5
+ - display
6
+ - position
7
+ - top
8
+ - right
9
+ - bottom
10
+ - left
11
+
12
+ flex:
13
+ - flex
14
+ - flex-basis
15
+ - flex-direction
16
+ - flex-flow
17
+ - flex-grow
18
+ - flex-shrink
19
+ - flex-wrap
20
+ - align-content
21
+ - align-items
22
+ - align-self
23
+ - justify-content
24
+ - order
25
+
26
+ box-dimensions:
27
+ - width
28
+ - min-width
29
+ - max-width
30
+ - height
31
+ - min-height
32
+ - max-height
33
+ - margin
34
+ - margin-top
35
+ - margin-right
36
+ - margin-bottom
37
+ - margin-left
38
+ - padding
39
+ - padding-top
40
+ - padding-right
41
+ - padding-bottom
42
+ - padding-left
43
+
44
+ float:
45
+ - float
46
+ - clear
47
+ - clip
48
+
49
+ columns:
50
+ - columns
51
+ - column-gap
52
+ - column-fill
53
+ - column-rule
54
+ - column-span
55
+ - column-count
56
+ - column-width
57
+
58
+ transform:
59
+ - transform
60
+ - transform-box
61
+ - transform-origin
62
+ - transform-style
63
+
64
+ transition:
65
+ - transition
66
+ - transition-delay
67
+ - transition-duration
68
+ - transition-property
69
+ - transition-timing-function
70
+
71
+ border:
72
+ - border
73
+ - border-top
74
+ - border-right
75
+ - border-bottom
76
+ - border-left
77
+ - border-width
78
+ - border-top-width
79
+ - border-right-width
80
+ - border-bottom-width
81
+ - border-left-width
82
+ - border-style
83
+ - border-top-style
84
+ - border-right-style
85
+ - border-bottom-style
86
+ - border-left-style
87
+ - border-radius
88
+ - border-top-left-radius
89
+ - border-top-right-radius
90
+ - border-bottom-left-radius
91
+ - border-bottom-right-radius
92
+ - border-color
93
+ - border-top-color
94
+ - border-right-color
95
+ - border-bottom-color
96
+ - border-left-color
97
+ - outline
98
+ - outline-color
99
+ - outline-offset
100
+ - outline-style
101
+ - outline-width
102
+
103
+ background:
104
+ - background
105
+ - background-attachment
106
+ - background-clip
107
+ - background-color
108
+ - background-image
109
+ - background-repeat
110
+ - background-position
111
+ - background-size
112
+
113
+ text:
114
+ - color
115
+ - font
116
+ - font-family
117
+ - font-size
118
+ - font-smoothing
119
+ - font-style
120
+ - font-variant
121
+ - font-weight
122
+ - letter-spacing
123
+ - line-height
124
+ - list-style
125
+ - text-align
126
+ - text-decoration
127
+ - text-indent
128
+ - text-overflow
129
+ - text-rendering
130
+ - text-shadow
131
+ - text-transform
132
+ - text-wrap
133
+ - white-space
134
+ - word-spacing
135
+
136
+ other:
137
+ - border-collapse
138
+ - border-spacing
139
+ - box-shadow
140
+ - caption-side
141
+ - content
142
+ - cursor
143
+ - empty-cells
144
+ - opacity
145
+ - overflow
146
+ - quotes
147
+ - speak
148
+ - table-layout
149
+ - vertical-align
150
+ - visibility
151
+ - z-index
@@ -0,0 +1,100 @@
1
+ # This is my own personal preference, included [a] to make my life easier, and [b] in case anyone is interested.
2
+ #
3
+ # Note that this is very much an ongoing process and may change at any time as I tweak and change things. Let me know
4
+ # what you think!
5
+ groups:
6
+ display:
7
+ properties:
8
+ - position
9
+ - display
10
+ - visibility
11
+ - overflow*
12
+ - float
13
+ - clear
14
+ - content
15
+ - box-sizing
16
+
17
+ flex-parent:
18
+ properties:
19
+ - flex-direction
20
+ - flex-wrap
21
+ - flex-flow
22
+ - justify-content
23
+ - align-items
24
+ - align-content
25
+
26
+ flex-child:
27
+ properties:
28
+ - flex
29
+ - order
30
+ - flex-grow
31
+ - flex-shrink
32
+ - flex-basis
33
+ - align-self
34
+
35
+ tables:
36
+ max_no_space: 1
37
+ properties:
38
+ - table-layout
39
+ - border-collapse
40
+ - empty-cells
41
+
42
+ dimensional:
43
+ properties:
44
+ - top
45
+ - left
46
+ - bottom
47
+ - right
48
+ - height
49
+ - min-height
50
+ - max-height
51
+ - width
52
+ - min-width
53
+ - max-width
54
+ - padding*
55
+ - margin*
56
+ - transform
57
+
58
+ presentational:
59
+ properties:
60
+ - outline*
61
+ - border
62
+ - border-style
63
+ - border-color
64
+ - border-radius
65
+ - border-width
66
+ - border-image
67
+ - border-top*
68
+ - border-right*
69
+ - border-bottom*
70
+ - border-left*
71
+ - background*
72
+ - opacity
73
+ - z-index
74
+ - color
75
+ - box-shadow
76
+ - filter
77
+
78
+ lists:
79
+ space_around: false
80
+ properties:
81
+ - counter*
82
+ - list-style*
83
+
84
+ text:
85
+ properties:
86
+ - font*
87
+ - line-height
88
+ - letter-spacing
89
+ - text-align
90
+ - text-decoration
91
+ - text-indent
92
+ - text-transform
93
+ - text-shadow
94
+ - white-space
95
+ - content
96
+
97
+ interaction:
98
+ properties:
99
+ - transition
100
+ - animation
data/data/smacss.yaml ADDED
@@ -0,0 +1,142 @@
1
+ # Note: whilst SMACSS defines groups, it doesn’t seem overly fussy about the order of properties within those groups.
2
+ # I could enforce some kind of subgrouping, but… that‘s not what SMACSS says and I don’t want to enforce something
3
+ # non-standard.
4
+ #
5
+ # You may wish to adapt this style to your own personal tastes =)
6
+ groups:
7
+ box:
8
+ - display
9
+ - position
10
+ - top
11
+ - right
12
+ - bottom
13
+ - left
14
+ - flex
15
+ - flex-basis
16
+ - flex-direction
17
+ - flex-flow
18
+ - flex-grow
19
+ - flex-shrink
20
+ - flex-wrap
21
+ - align-content
22
+ - align-items
23
+ - align-self
24
+ - justify-content
25
+ - order
26
+ - width
27
+ - min-width
28
+ - max-width
29
+ - height
30
+ - min-height
31
+ - max-height
32
+ - margin
33
+ - margin-top
34
+ - margin-right
35
+ - margin-bottom
36
+ - margin-left
37
+ - padding
38
+ - padding-top
39
+ - padding-right
40
+ - padding-bottom
41
+ - padding-left
42
+ - float
43
+ - clear
44
+ - clip
45
+ - columns
46
+ - column-gap
47
+ - column-fill
48
+ - column-rule
49
+ - column-span
50
+ - column-count
51
+ - column-width
52
+ - transform
53
+ - transform-box
54
+ - transform-origin
55
+ - transform-style
56
+ - transition
57
+ - transition-delay
58
+ - transition-duration
59
+ - transition-property
60
+ - transition-timing-function
61
+
62
+ border:
63
+ - border
64
+ - border-top
65
+ - border-right
66
+ - border-bottom
67
+ - border-left
68
+ - border-width
69
+ - border-top-width
70
+ - border-right-width
71
+ - border-bottom-width
72
+ - border-left-width
73
+ - border-style
74
+ - border-top-style
75
+ - border-right-style
76
+ - border-bottom-style
77
+ - border-left-style
78
+ - border-radius
79
+ - border-top-left-radius
80
+ - border-top-right-radius
81
+ - border-bottom-left-radius
82
+ - border-bottom-right-radius
83
+ - border-color
84
+ - border-top-color
85
+ - border-right-color
86
+ - border-bottom-color
87
+ - border-left-color
88
+ - outline
89
+ - outline-color
90
+ - outline-offset
91
+ - outline-style
92
+ - outline-width
93
+
94
+ background:
95
+ - background
96
+ - background-attachment
97
+ - background-clip
98
+ - background-color
99
+ - background-image
100
+ - background-repeat
101
+ - background-position
102
+ - background-size
103
+
104
+ text:
105
+ - color
106
+ - font
107
+ - font-family
108
+ - font-size
109
+ - font-smoothing
110
+ - font-style
111
+ - font-variant
112
+ - font-weight
113
+ - letter-spacing
114
+ - line-height
115
+ - list-style
116
+ - text-align
117
+ - text-decoration
118
+ - text-indent
119
+ - text-overflow
120
+ - text-rendering
121
+ - text-shadow
122
+ - text-transform
123
+ - text-wrap
124
+ - white-space
125
+ - word-spacing
126
+
127
+ other:
128
+ - border-collapse
129
+ - border-spacing
130
+ - box-shadow
131
+ - caption-side
132
+ - content
133
+ - cursor
134
+ - empty-cells
135
+ - opacity
136
+ - overflow
137
+ - quotes
138
+ - speak
139
+ - table-layout
140
+ - vertical-align
141
+ - visibility
142
+ - z-index
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'grouped_property_scss_linter/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "grouped_property_scss_linter"
8
+ spec.version = GroupedPropertyScssLinter::VERSION
9
+ spec.authors = ["Jon Pearse"]
10
+ spec.email = ["jon@jonpearse.net"]
11
+ spec.summary = "SCSS Lint plugin"
12
+ spec.description = "Plugin for SCSS lint that lints the order of properties based on fuzzy groups"
13
+ spec.homepage = "https://github.com/jonpearse/grouped_property_scss_linter"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.6"
20
+ spec.add_development_dependency "rake", '~> 0'
21
+
22
+ spec.add_dependency 'scss_lint', '~> 0'
23
+ end
data/lib/ext/string.rb ADDED
@@ -0,0 +1,9 @@
1
+ class String
2
+
3
+ def bold
4
+
5
+ "\e[1m#{self}\e[0m"
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ require "grouped_property_scss_linter/version"
2
+ require "grouped_property_scss_linter/grouped_property_order"
3
+ require "ext/string"
4
+
5
+ module GroupedPropertyScssLinter
6
+
7
+ STYLES_DIR = File.realpath(File.join(File.dirname(__FILE__), '..', 'data')).freeze
8
+
9
+ end
@@ -0,0 +1,310 @@
1
+ module SCSSLint
2
+ class Linter::GroupedPropertyOrder < Linter
3
+ include LinterRegistry
4
+
5
+ # Called when the linter is fired up on a document. Acts as a pseudo-constructor
6
+ def visit_root( node )
7
+
8
+ # get configured order
9
+ @configured_groups = get_order_from_conf
10
+
11
+ # and map things around
12
+ @groups = []
13
+ @property_to_group = {}
14
+ count = 0
15
+ @configured_groups.each_pair do |name, group|
16
+ @groups.push name
17
+ group['properties'].each do |property|
18
+ @property_to_group[property] = { name: name, idx: count }
19
+ end
20
+ count = count+1
21
+ end
22
+
23
+ yield
24
+
25
+ end
26
+
27
+ # Logic that actually performs order
28
+ def check_order( node )
29
+
30
+ # 1. get a list of properties we can sort
31
+ sortable_properties = node.children.select do |child|
32
+ child.is_a? Sass::Tree::PropNode
33
+ end
34
+
35
+ # 2. group things
36
+ grouped_properties = {}
37
+ props = sortable_properties.map do |prop|
38
+
39
+ # simplify the name a little
40
+ name = prop.name.join
41
+
42
+ # attempt to match the name
43
+ group = find_match_for_property name
44
+
45
+ # if it didn’t find anything, move on
46
+ next if group.nil?
47
+
48
+ # if there’s no existing group
49
+ unless grouped_properties.key? group[:name]
50
+ grouped_properties[group[:name]] = { first: 1.0/0, last: 0, props: [] }
51
+ end
52
+
53
+ # build a concat
54
+ concat = { name: name, node: prop, group: group[:name], line: prop.line, group_idx: group[:idx] }
55
+
56
+ # drop things on
57
+ grouped_properties[group[:name]][:first] = [grouped_properties[group[:name]][:first], prop.line].min
58
+ grouped_properties[group[:name]][:last] = [grouped_properties[group[:name]][:last], prop.line].max
59
+ grouped_properties[group[:name]][:props] << concat
60
+
61
+ concat
62
+
63
+ end
64
+ props.compact!
65
+
66
+ # 3. call down
67
+ unless grouped_properties.empty?
68
+ check_sort_order props, grouped_properties
69
+ end
70
+
71
+ # 4. yield so we can process children
72
+ yield
73
+
74
+ end
75
+
76
+ # alias things out
77
+ alias visit_media check_order
78
+ alias visit_mixin check_order
79
+ alias visit_rule check_order
80
+ alias visit_prop check_order
81
+
82
+ def visit_if(node, &block)
83
+ check_order(node, &block)
84
+ visit(node.else) if node.else
85
+ end
86
+
87
+ private
88
+
89
+ # Acquires configuration and populates out a group array
90
+ def get_order_from_conf
91
+
92
+ # 1. acquire defaults + default them, just in case
93
+ defaults = config['defaults']
94
+ defaults['space_around'] |= true
95
+ defaults['max_no_space'] |= 3
96
+
97
+ # 2, acquire groups
98
+ groups = config['groups'] || load_groups_from_style
99
+
100
+ # 3. if it failed, bail
101
+ raise 'No groups configured' if groups.nil?
102
+
103
+ # 4. munge
104
+ groups.update(groups) do |name, group|
105
+
106
+ # a. if it’s an array, cast it
107
+ group = { 'properties' => group } if group.is_a? Array
108
+
109
+ # b. merge in some defaults
110
+ group['space_around'] = defaults['space_around'] if group['space_around'].nil?
111
+ group['max_no_space'] ||= defaults['max_no_space']
112
+
113
+ # c. return
114
+ group
115
+
116
+ end
117
+
118
+ groups
119
+
120
+ end
121
+
122
+ # Loads a group from a configured style
123
+ def load_groups_from_style
124
+
125
+ # 0. if the style is blank/empty…
126
+ (raise 'No style specified' and return) if config['style'].empty?
127
+
128
+ # 1. attempt to find the file
129
+ data_filename = File.join(GroupedPropertyScssLinter::STYLES_DIR, "#{config['style']}.yaml")
130
+
131
+ # 2. does it exist
132
+ (raise "No style ‘#{config['style']}’ found" and return) unless File.exists? data_filename
133
+
134
+ # 3. can we read it
135
+ (raise "Cannot read style ‘#{config['style']}’" and return) unless File.readable? data_filename
136
+
137
+ # 4. open
138
+ style_config = YAML.load_file data_filename
139
+
140
+ # 5. barf?
141
+ (raise "Bad style file found for ‘#{config['style']}’" and return) if style_config.nil? or style_config['groups'].nil?
142
+
143
+ style_config['groups']
144
+ end
145
+
146
+ # Finds a matching group for a specified property
147
+ def find_match_for_property( prop )
148
+
149
+ # sanitise the name by removing any browser prefixes
150
+ prop = prop.gsub(/^(-\w+(-osx)?-)?/, '')
151
+
152
+ # iteratively remove hyphens from the property…
153
+ while prop =~ /\-/
154
+
155
+ # if we know about this property or its splatted variety…
156
+ if @property_to_group.key? prop or @property_to_group.key? prop+'*'
157
+
158
+ return @property_to_group[prop] || @property_to_group[prop+'*']
159
+
160
+ end
161
+
162
+ prop.gsub! /\-(\w+)$/, ''
163
+
164
+ end
165
+
166
+ # finally…
167
+ if @property_to_group.key? prop or @property_to_group.key? prop+'*'
168
+
169
+ return @property_to_group[prop] || @property_to_group[prop+'*']
170
+
171
+ end
172
+
173
+ nil
174
+
175
+ end
176
+
177
+ def check_sort_order( props, grouped )
178
+
179
+ # get stats on grouped version
180
+ grouped.each_value do |group|
181
+
182
+ # number of properties
183
+ group[:num] = group[:props].length
184
+ group[:delta] = group[:last] - group[:first]
185
+
186
+ end
187
+
188
+ # quick duck-type
189
+ quick_check_order props, grouped
190
+
191
+ # if we’re checking whitespace, do so
192
+ check_whitespace( grouped ) unless grouped.length < 2
193
+
194
+ end
195
+
196
+ def quick_check_order( props, grouped )
197
+
198
+ current_group = 0
199
+ good = true
200
+
201
+ props.each do |prop|
202
+
203
+ # if it’s the current group, move on
204
+ next if prop[:group] == @groups[current_group]
205
+
206
+ # find an index
207
+ idx = @groups.index prop[:group]
208
+
209
+ # if it’s less-than, error out
210
+ if idx < current_group
211
+
212
+ ext = config['extended_hinting'] ? " (assigned group ‘#{prop[:group].bold}’, found group ‘#{@groups[current_group].bold}’)" : ""
213
+
214
+ add_lint prop[:node], "property ‘#{prop[:name].bold}’ should be #{hint_text_for(prop, grouped, props)}#{ext}"
215
+ good = false
216
+ else
217
+ current_group = idx
218
+ end
219
+
220
+ end
221
+
222
+ good
223
+
224
+ end
225
+
226
+ def check_whitespace( grouped )
227
+
228
+ # get a quick handle on all the groups we’ve found
229
+ detected_groups = grouped.keys
230
+
231
+ # iterate through
232
+ curr_idx = 0
233
+ grouped.each_pair do |name, current|
234
+
235
+ # get a configuration
236
+ group_conf = @configured_groups[name]
237
+
238
+ # if we don’t care about space, bail
239
+ (curr_idx += 1 and next) unless group_conf['space_around']
240
+
241
+ # similarly, if this group is too small to trigger spacing, bounce
242
+ (curr_idx += 1 and next)unless current[:props].length > group_conf['max_no_space']
243
+
244
+ # set some easy references
245
+ next_group = detected_groups.length > curr_idx ? grouped[detected_groups[curr_idx + 1]] : nil
246
+ prev_group = curr_idx > 0 ? grouped[detected_groups[curr_idx - 1]] : nil
247
+
248
+ # if there’s something after us, and there’s no space
249
+ if !next_group.nil? and ((next_group[:first] - current[:last]) < 2)
250
+
251
+ # raise a lint error
252
+ add_lint current[:props].last[:node], "Must be at least one empty line after ‘#{current[:props].last[:name]}’"
253
+
254
+ # also, flag the next group so we don’t catch it next time ‘round
255
+ next_group[:raised] = true
256
+ end
257
+
258
+ # if there’s something before us, and there’s no space…
259
+ if !prev_group.nil? and ((current[:first] - prev_group[:last]) < 2) and current[:raised].nil?
260
+
261
+ # raise a lint error
262
+ add_lint current[:props].first[:node], "Must be at least one empty line before ‘#{current[:props].first[:name]}’"
263
+
264
+ end
265
+
266
+ # finally, increment
267
+ curr_idx += 1
268
+
269
+ end
270
+ end
271
+
272
+ def hint_text_for( prop, grouped_props, context )
273
+
274
+ # get target group
275
+ dst_group = prop[:group]
276
+
277
+ # if we know about the group…
278
+ if grouped_props.key? dst_group
279
+
280
+ # get the first property of the current group
281
+ dst_prop = grouped_props[dst_group][:props].first
282
+
283
+ # if it’s a different property, return
284
+ return "after ‘#{dst_prop[:name].bold}’" if dst_prop != prop
285
+ end
286
+
287
+ # either our offending property is the sole member of a group, or it’s very lost… so look for a previous marker
288
+ curr_idx = prop[:group_idx]
289
+ while curr_idx > 0
290
+
291
+ # decrement and reset
292
+ curr_idx = curr_idx - 1
293
+ dst_group = @groups[curr_idx]
294
+
295
+ # look
296
+ if grouped_props.key? dst_group
297
+
298
+ # get the _last_ property of the group
299
+ dst_prop = grouped_props[dst_group][:props].last
300
+
301
+ # and return
302
+ return "after ‘#{dst_prop[:name].bold}’"
303
+ end
304
+ end
305
+
306
+ # otherwise, it probably belongs right at the start
307
+ "before ‘#{context.first[:name].bold}’"
308
+ end
309
+ end
310
+ end
@@ -0,0 +1,3 @@
1
+ module GroupedPropertyScssLinter
2
+ VERSION = "1.1.3"
3
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grouped_property_scss_linter
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Jon Pearse
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: scss_lint
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Plugin for SCSS lint that lints the order of properties based on fuzzy
56
+ groups
57
+ email:
58
+ - jon@jonpearse.net
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".scss-lint.yml"
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.textile
68
+ - Rakefile
69
+ - data/concentric.yaml
70
+ - data/grouped-smacss.yaml
71
+ - data/personal.yaml
72
+ - data/smacss.yaml
73
+ - grouped_property_scss_linter.gemspec
74
+ - lib/ext/string.rb
75
+ - lib/grouped_property_scss_linter.rb
76
+ - lib/grouped_property_scss_linter/grouped_property_order.rb
77
+ - lib/grouped_property_scss_linter/version.rb
78
+ homepage: https://github.com/jonpearse/grouped_property_scss_linter
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.6.10
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: SCSS Lint plugin
102
+ test_files: []