dss_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: