dss_parser 1.0.0

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,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZmQwMDI0MzgwYzdiMmEzZGEzOTcxODZiMWNkMzMwMjU0YzJkZjYyZA==
5
+ data.tar.gz: !binary |-
6
+ NzY3OGMxYTZkNWEzMjhmM2MxOGNhY2Y3ZmNhMjc3ODJiNTU4YWYzMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YmJjZDExNGY5ZTdhZWE1Yjg3MzNjODE3MDRhYzI3OTFlZDhkMjY5N2M4ZDVm
10
+ NzY2ZWRkMzJhMzYxNzhjYWJmMzk5ODBkODNhODVjYjFjMDZhMmQwMjkzMDA3
11
+ NzI2MTBiMThmYTY2NjVjMGNiMTRmMjlhZWNkNDkxMjhkZTE2Yjc=
12
+ data.tar.gz: !binary |-
13
+ MjdjZmFkZTI4NWM2NGU2ODM4ZWQyZTEzNzEyOTJmZmE1ODI0MzQ1ZTM3NGZj
14
+ MWFhN2M1MDNlOWM4NDYxNWJkZTYzM2I5NjFmYzFhOTY5MGMzYTY2MGYzYjY1
15
+ M2QxMzljNzI5N2Y3NDVmNjJmYTk5YmM0MDZhMWMxNWI5M2Q5NjA=
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dss-parser.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, cmd: 'bundle exec rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Spicerack Media Ltd
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.md ADDED
@@ -0,0 +1,73 @@
1
+ # DSS Parser for Ruby
2
+
3
+ A parser for DSS comments in CSS.
4
+
5
+ DSS allows documentation of CSS using comments in CSS files, designed to be machine readable for living style guides. For more information on DSS [https://github.com/DSSWG/DSS](https://github.com/DSSWG/DSS).
6
+
7
+ This has a couple of additional parsers beyond the DSS spec
8
+ - Variables for mixins in scss
9
+ - Section to organise the classes
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'dss-parser'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install dss-parser
26
+
27
+ ## Usage
28
+
29
+ To use DSS create an instance of dss-parser parsing in a folder containing your css. It will recusivly pass any css/scss files in that directory. And then find any DSS comments.
30
+
31
+ ```ruby
32
+ parser = DssParser.new('/path/to/stylesheets')
33
+ dss = parser.get_dss
34
+ ```
35
+
36
+ This will create an array of DSS comments that can be used e.g.
37
+
38
+ ```ruby
39
+ dss.each do |d|
40
+ d.name
41
+ d.description
42
+ d.markup
43
+ d.section
44
+ d.states.each do |state|
45
+ state.name
46
+ state.description
47
+ end
48
+ d.variables.each do |variable|
49
+ variable.name
50
+ variable.description
51
+ end
52
+ end
53
+ ```
54
+
55
+ ## Additional Parsers
56
+
57
+ The gem contains parsers for the main DSS attributes but can be extended with your own parsers.
58
+
59
+ ```ruby
60
+ parser = DssParser.new('/path/to/stylesheet')
61
+ parser.register_parser(MyParser::AdditionalAttribute)
62
+ dss = parser.get_dss
63
+ ```
64
+
65
+ To create your own parser take a look at the parsers in lib/dss_parser/parsers.
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it ( https://github.com/[my-github-username]/dss-parser/fork )
70
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
71
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
72
+ 4. Push to the branch (`git push origin my-new-feature`)
73
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dss_parser/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dss_parser"
8
+ spec.version = DssParser::VERSION
9
+ spec.authors = ["Graham Hadgraft"]
10
+ spec.email = ["graham@spicerack.co.uk"]
11
+ spec.summary = %q{A parser for DSS comments}
12
+ spec.description = %q{Parses DSS comments from css files}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0.0"
24
+ spec.add_development_dependency "guard-rspec"
25
+ end
data/lib/dss_parser.rb ADDED
@@ -0,0 +1,130 @@
1
+ PARSER_PATH = "#{File.expand_path('../..', __FILE__)}/lib/dss_parser/parsers/*.rb"
2
+
3
+ require 'ostruct'
4
+ require "dss_parser/version"
5
+ Dir[PARSER_PATH].each {|file| require file }
6
+
7
+ class DssParser
8
+ def initialize(stylesheet_path)
9
+ @stylesheet_path = stylesheet_path
10
+ @parsers = [DssParser::Parser::Name,
11
+ DssParser::Parser::Description,
12
+ DssParser::Parser::States,
13
+ DssParser::Parser::Markup,
14
+ DssParser::Parser::Variables,
15
+ DssParser::Parser::Section]
16
+ end
17
+
18
+ def get_dss
19
+ comments = []
20
+
21
+ find_css_files.each do |file_path|
22
+ css_file = IO.read(file_path)
23
+ comments |= parse_for_comments(css_file)
24
+ end
25
+
26
+ comments.map! { |c| build_dss(c) }
27
+ end
28
+
29
+ def register_parser(parser)
30
+ @parsers.push parser
31
+ end
32
+
33
+ private
34
+
35
+ def parse_for_comments(css)
36
+ lines = css.split "\n"
37
+
38
+ css_comments = find_css_comments(lines)
39
+ sass_comments = find_sass_comments(lines)
40
+
41
+ strip_whitespace(css_comments | sass_comments)
42
+ end
43
+
44
+ def build_dss(comment)
45
+ dss = []
46
+ @parsers.each do |parser|
47
+ parsed_content = parser.parse(comment)
48
+ dss.push parsed_content unless parsed_content.nil?
49
+ end
50
+ OpenStruct.new(dss.reduce({}, :merge))
51
+ end
52
+
53
+ def find_css_files
54
+ Dir.glob("#{@stylesheet_path}**/*.css*")
55
+ end
56
+
57
+ def find_sass_comments(lines)
58
+ in_comment = false
59
+ current_comment = []
60
+ comment_blocks = []
61
+
62
+ lines.each do |line_of_css|
63
+ line_of_css.strip!
64
+
65
+ if scss_comment?(line_of_css) || in_comment == true
66
+ in_comment = true
67
+
68
+ current_comment.push line_of_css
69
+ unless line_of_css.start_with?('//')
70
+ in_comment = false
71
+ end
72
+ else
73
+ in_comment = false
74
+ comment_blocks.push current_comment if is_dss_comment?(current_comment)
75
+ current_comment = []
76
+ end
77
+ end
78
+
79
+ comment_blocks
80
+ end
81
+
82
+ def find_css_comments(lines)
83
+ in_comment = false
84
+ current_comment = []
85
+ comment_blocks = []
86
+
87
+ lines.each do |line_of_css|
88
+ line_of_css.strip!
89
+
90
+ if css_comment?(line_of_css) || in_comment == true
91
+ in_comment = true
92
+ current_comment.push line_of_css
93
+ if line_of_css.end_with?('*/')
94
+ in_comment = false
95
+ end
96
+ else
97
+ in_comment = false
98
+ comment_blocks.push current_comment if is_dss_comment?(current_comment)
99
+ current_comment = []
100
+ end
101
+ end
102
+
103
+ comment_blocks
104
+ end
105
+
106
+ def is_dss_comment?(comment)
107
+ comment.any? { |line| line.downcase.include?("@name") || line.downcase.include?("@mixin") }
108
+ end
109
+
110
+ def css_comment?(line)
111
+ line.start_with?('/*','*/') && !line.end_with?('*/')
112
+ end
113
+
114
+ def scss_comment?(line)
115
+ line.start_with? '//'
116
+ end
117
+
118
+ def strip_whitespace(comment_blocks)
119
+ comment_blocks.each do |comment|
120
+ comment.map!{ |c| c.gsub(/^\/\//, '') }
121
+ comment.map!{ |c| c.gsub(/^\/\*/, '') }
122
+ comment.map!{ |c| c.gsub(/^\*\//, '') }
123
+ comment.map!{ |c| c.gsub(/^\*/, '') }
124
+ comment.map!{ |c| c.strip }
125
+ comment.reject!{ |c| c.size < 1 }
126
+ end
127
+
128
+ comment_blocks.reject{ |c| c.size < 1 }
129
+ end
130
+ end
@@ -0,0 +1,30 @@
1
+ class DssParser
2
+ class Parser
3
+ class Description
4
+ def self.parse(lines)
5
+ description = []
6
+ in_description = false
7
+
8
+ lines.each do |line|
9
+ if line.start_with?("@") && line !~ /^@description/ && in_description
10
+ in_description = false
11
+ end
12
+
13
+ if line.start_with?("@")
14
+ type, content = line.split(" ", 2)
15
+ if type == "@description"
16
+ in_description = true
17
+ description.push content
18
+ end
19
+ else
20
+ if in_description == true
21
+ description.push line
22
+ end
23
+ end
24
+ end
25
+
26
+ return {description: description.join("\n")}
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ class DssParser
2
+ class Parser
3
+ class Markup
4
+ def self.parse(lines)
5
+ markup = []
6
+ in_markup = false
7
+
8
+ lines.each do |line|
9
+ if line.start_with?("@") && line !~ /^@markup/ && in_markup
10
+ in_description = false
11
+ end
12
+
13
+ if line.start_with?("@")
14
+ type, content = line.split(" ", 2)
15
+ if type == "@markup"
16
+ in_markup = true
17
+ markup.push content
18
+ end
19
+ else
20
+ if in_markup == true
21
+ markup.push line
22
+ end
23
+ end
24
+ end
25
+
26
+ return {markup: markup.join("\n").gsub(/^\n/, '')}
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ class DssParser
2
+ class Parser
3
+ class Name
4
+
5
+ def self.parse(lines)
6
+ lines.each do |line|
7
+ type, content = line.split(" ", 2)
8
+
9
+ return {name: content} if type == "@name"
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ class DssParser
2
+ class Parser
3
+ class Section
4
+ def self.parse(lines)
5
+ section = {}
6
+
7
+ lines.each do |line|
8
+ type, content = line.split(" ", 2)
9
+
10
+ if type == "@section"
11
+ section = {section: content}
12
+ end
13
+ end
14
+
15
+ return section
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ class DssParser
2
+ class Parser
3
+ class States
4
+ def self.parse(lines)
5
+ states = []
6
+ Struct.new("State", :name, :description) unless defined?(Struct::State)
7
+
8
+ lines.each do |line|
9
+ type, content = line.split(" ", 2)
10
+
11
+ if type == "@state"
12
+ name, description = content.split("-", 2)
13
+
14
+ states.push(Struct::State.new(name.strip, description.strip))
15
+ end
16
+ end
17
+
18
+ return {states: states}
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ class DssParser
2
+ class Parser
3
+ class Variables
4
+ def self.parse(lines)
5
+ variables = []
6
+ Struct.new("Variable", :name, :description) unless defined?(Struct::Variable)
7
+
8
+ lines.each do |line|
9
+ type, content = line.split(" ", 2)
10
+
11
+ if type == "@variable"
12
+ name, description = content.split("-", 2)
13
+
14
+ variables.push(Struct::Variable.new(name.strip, description.strip))
15
+ end
16
+ end
17
+
18
+ return {variables: variables}
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ class DssParser
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @name Gradient($Start, $End)
3
+ * @description Add a gradient to element
4
+ *
5
+ * @variable $Start - A hex color at the top of the gradient
6
+ * @variable $End - A hex color at the bottom of the gradient
7
+ *
8
+ */
9
+
10
+ @mixin gradient($start, $end){
11
+
12
+ }
13
+
14
+ /* A non dss comment */
15
+
16
+ /*
17
+ @name Button
18
+ @description Style for a button
19
+ this is a multiline description
20
+ @section Forms.Buttons
21
+
22
+ @state :disabled - Dims the button when disabled.
23
+ @state .primary - Indicates button is the primary action.
24
+ @state .smaller - A smaller button
25
+
26
+ @markup
27
+ <button>markup</button>
28
+ */
29
+
30
+ button {
31
+ max-width: 150px;
32
+
33
+ .full-width {
34
+ width:100%;
35
+ }
36
+ }
37
+
38
+
39
+
@@ -0,0 +1,53 @@
1
+ //
2
+ // @name Text Input
3
+ // @description Style for a input with type text
4
+ // @section Forms.Inputs
5
+ //
6
+ // @state :disabled - Dims the button when disabled.
7
+ // @state .primary - Indicates button is the primary action.
8
+ // @state .smaller - A smaller button
9
+ //
10
+ // @markup
11
+ // <button>markup<button>
12
+ //
13
+
14
+ input[type="text"] {
15
+ max-width: 150px;
16
+
17
+ .full-width {
18
+ width:100%;
19
+ }
20
+ }
21
+
22
+ // This
23
+ // is
24
+ // not
25
+ // a
26
+ // dss
27
+ // comment
28
+
29
+ .non-documented-class {
30
+
31
+ }
32
+
33
+ //
34
+ // @name Submit Input
35
+ // @description Style for an input with type button
36
+ // @section Forms.Inputs
37
+ //
38
+ // @state :disabled - Dims the button when disabled.
39
+ // @state .primary - Indicates button is the primary action.
40
+ // @state .smaller - A smaller button
41
+ //
42
+ // @markup
43
+ // <button>markup<button>
44
+ //
45
+
46
+ input[type="submit"] {
47
+ max-width: 150px;
48
+
49
+ .full-width {
50
+ width:100%;
51
+ }
52
+ }
53
+
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe DssParser do
4
+ describe '#get_comments' do
5
+ it 'finds comments in css files' do
6
+ parser = DssParser.new("#{File.expand_path('../..', __FILE__)}/fixtures/")
7
+ comments = parser.get_dss
8
+
9
+ expect(comments.size).to eq 4
10
+ end
11
+
12
+ it 'finds dss attributes in dss comments' do
13
+ parser = DssParser.new("#{File.expand_path('../..', __FILE__)}/fixtures/")
14
+ comments = parser.get_dss
15
+
16
+ mixin = comments[0]
17
+ dss_button = comments[1]
18
+
19
+ expect(dss_button.name).to eq "Button"
20
+ expect(dss_button.description).to eq "Style for a button\nthis is a multiline description"
21
+ expect(dss_button.states.size).to eq 3
22
+ expect(dss_button.states.first.name).to eq ":disabled"
23
+ expect(dss_button.states.first.description).to eq "Dims the button when disabled."
24
+ expect(dss_button.markup).to eq "<button>markup</button>"
25
+ expect(dss_button.section).to eq "Forms.Buttons"
26
+
27
+ expect(mixin.variables.size).to eq 2
28
+ expect(mixin.variables.first.name).to eq "$Start"
29
+ expect(mixin.variables.first.description).to eq "A hex color at the top of the gradient"
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'dss_parser' # and any other gems you need
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dss_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Graham Hadgraft
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-08 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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 3.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Parses DSS comments from css files
70
+ email:
71
+ - graham@spicerack.co.uk
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - Guardfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - dss-parser.gemspec
83
+ - lib/dss_parser.rb
84
+ - lib/dss_parser/parsers/description.rb
85
+ - lib/dss_parser/parsers/markup.rb
86
+ - lib/dss_parser/parsers/name.rb
87
+ - lib/dss_parser/parsers/section.rb
88
+ - lib/dss_parser/parsers/states.rb
89
+ - lib/dss_parser/parsers/variables.rb
90
+ - lib/dss_parser/version.rb
91
+ - spec/fixtures/buttons.css
92
+ - spec/fixtures/forms.css.scss
93
+ - spec/lib/dss_parser_spec.rb
94
+ - spec/spec_helper.rb
95
+ homepage: ''
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.2.1
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: A parser for DSS comments
119
+ test_files:
120
+ - spec/fixtures/buttons.css
121
+ - spec/fixtures/forms.css.scss
122
+ - spec/lib/dss_parser_spec.rb
123
+ - spec/spec_helper.rb
124
+ has_rdoc: