dss 0.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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/dss.rb +222 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a445249839686ccdd17fc7712de1db28219fd7e3
4
+ data.tar.gz: cc9b60f3007009e24c77a94459b13162ad61dc06
5
+ SHA512:
6
+ metadata.gz: ee20336d485251e7162fcdd698d7fc5a6b15a421516cbb9a088839a8afa0ea7bcd1b428499772cf3078d892a65b58f2b4112308a4464f593b990c8216d1a6f4a
7
+ data.tar.gz: 20cddc2196de944f13714842efd5d6b331d6fa92f30a483c54e090027a177c3bdde5e589e54d4e6d02f41d724fc7f21ccc7b0d5800039b6ae61569a8510efff1
data/lib/dss.rb ADDED
@@ -0,0 +1,222 @@
1
+ class DSS
2
+ def initialize
3
+ def default_parser(output)
4
+ output[:line][:contents]
5
+ end
6
+
7
+ def state_parser(output)
8
+ state = output[:line][:contents].split(' - ');
9
+ [{
10
+ name: (state[0]) ? trim_whitespace(state[0]) : '',
11
+ escaped: (state[0]) ? trim_whitespace(state[0].gsub('.', ' ').gsub(':', ' pseudo-class-')) : '',
12
+ description: (state[1]) ? trim_whitespace(state[1]) : ''
13
+ }];
14
+ end
15
+
16
+ def markup_parser(output)
17
+ [{
18
+ example: output[:line][:contents],
19
+ escaped: output[:line][:contents].gsub(/</, '&lt;').gsub(/>/, '&gt;')
20
+ }]
21
+ end
22
+
23
+ @parsers = {
24
+ name: method(:default_parser),
25
+ description: method(:default_parser),
26
+ state: method(:state_parser),
27
+ markup: method(:markup_parser)
28
+ }
29
+ end
30
+
31
+ def detect(line)
32
+ if !line.is_a?(String)
33
+ false
34
+ end
35
+ reference = line.split("\n\n").pop
36
+ !!(/.*@/).match(reference)
37
+ end
38
+
39
+ def detector(callback)
40
+ # TODO: Figure out how to do this, or why it's even necessary
41
+ # DSS.class_eval do
42
+ # %Q{def detect(args) #{callback}.call(args) end}
43
+ # end
44
+ end
45
+
46
+ def parser(name, callback)
47
+ @parsers[name.to_sym] = callback
48
+ end
49
+
50
+ def alias(newName, oldName)
51
+ @parsers[newName.to_sym] = @parsers[oldName.to_sym]
52
+ end
53
+
54
+ def parse_line(_temp, line, block, file, from, to, options)
55
+ temp = _temp
56
+ parts = line.gsub(/.*@/, '')
57
+ index = parts.index(' ') || parts.index(/\n/) || parts.index(/\r/) || parts.length
58
+ name = trim_whitespace(parts[0..index]).to_sym
59
+ output = {
60
+ options: options,
61
+ file: file,
62
+ name: name,
63
+ line: {
64
+ contents: nil,
65
+ from: block.index(line),
66
+ to: block.index(line)
67
+ },
68
+ block: {
69
+ contents: block,
70
+ from: from,
71
+ to: to
72
+ }
73
+ }
74
+
75
+ next_parser_index = block.index('@', output[:line][:from] + 1)
76
+ markup_length = !next_parser_index.nil? ? next_parser_index - output[:line][:from] : block.length
77
+ parser_marker = "@#{name}"
78
+ contents = block.split('').slice(output[:line][:from], markup_length).join('').gsub(parser_marker, '')
79
+ output[:line][:contents] = trim_whitespace(normalize(contents))
80
+
81
+ new_line = {}
82
+ new_line[name] = !@parsers[name.to_sym].nil? ? @parsers[name.to_sym].call(output) : ''
83
+
84
+ if (temp[name])
85
+ if !temp[name].is_a?(Array)
86
+ temp[name] = [temp[name]]
87
+ end
88
+ if !new_line[name].is_a?(Array)
89
+ temp[name].push(new_line[name])
90
+ else
91
+ temp[name].push(new_line[name][0])
92
+ end
93
+ else
94
+ temp = temp.merge(new_line)
95
+ end
96
+ temp
97
+ end
98
+
99
+ def parse(lines, options = {})
100
+ current_block = ''
101
+ inside_single_line_block = false
102
+ inside_multi_line_block = false
103
+ unparsed_blocks = []
104
+ trimmed = ''
105
+ parsed_blocks = []
106
+ temp = {}
107
+ line_num = 0
108
+ from = 0
109
+ to = 0
110
+
111
+ lines.to_s.split(/\n/).each do |line|
112
+ line_num += 1
113
+
114
+ if single_line_comment(line) || start_multi_line_comment(line)
115
+ from = line_num
116
+ end
117
+
118
+ if single_line_comment(line)
119
+ trimmed = trim_single_line(line)
120
+ if inside_single_line_block
121
+ current_block += "\n#{trimmed}"
122
+ else
123
+ current_block = trimmed
124
+ inside_single_line_block = true
125
+ end
126
+ end
127
+
128
+ if start_multi_line_comment(line) || inside_multi_line_block
129
+ trimmed = trim_multi_line(line)
130
+ if inside_multi_line_block
131
+ current_block += "\n#{trimmed}"
132
+ else
133
+ current_block += trimmed
134
+ inside_multi_line_block = true
135
+ end
136
+ end
137
+
138
+ if end_multi_line_comment(line)
139
+ inside_multi_line_block = false
140
+ end
141
+
142
+ if !single_line_comment(line) && !inside_multi_line_block
143
+ if current_block
144
+ unparsed_blocks.push({ text: normalize(current_block), from: from, to: line_num })
145
+ end
146
+ inside_single_line_block = false
147
+ current_block = ''
148
+ end
149
+ end
150
+
151
+ unparsed_blocks.each do |_block|
152
+ from = _block[:from]
153
+ to = _block[:to]
154
+ block = _block[:text].split(/\n/).select do |line|
155
+ line.length > 0
156
+ end
157
+ block = block.join("\n")
158
+
159
+ block.split(/\n/).each do |line|
160
+ if detect(line)
161
+ temp = parse_line(temp, normalize(line), block, lines, from, to, options)
162
+ end
163
+ end
164
+
165
+ if temp.length > 0
166
+ parsed_blocks.push(temp)
167
+ end
168
+ temp = {}
169
+ end
170
+ { blocks: parsed_blocks }
171
+ end
172
+
173
+ private
174
+
175
+ def trim_whitespace(str)
176
+ patterns = [/\A\s\s*/, /\s\s*\z/]
177
+ trimmed_str = str
178
+ patterns.each do |regEx|
179
+ trimmed_str = trimmed_str.gsub(regEx, '')
180
+ end
181
+ trimmed_str
182
+ end
183
+
184
+ def single_line_comment(line)
185
+ !!(/\A\s*\/\//).match(line)
186
+ end
187
+
188
+ def start_multi_line_comment(line)
189
+ !!(/\A\s*\/\*/).match(line)
190
+ end
191
+
192
+ def trim_single_line(line)
193
+ line.gsub(/\s*\/\//, '')
194
+ end
195
+
196
+ def trim_multi_line(line)
197
+ line.gsub(/\A.*(\/\*|\*\/|\*)+/, '')
198
+ end
199
+
200
+ def end_multi_line_comment(line)
201
+ if single_line_comment(line)
202
+ false
203
+ end
204
+ !!(/.*\*\//).match(line)
205
+ end
206
+
207
+ def normalize(text_block)
208
+ indent_size = nil
209
+ normalized = text_block.split(/\n/).map do |line|
210
+ preceding_whitespace = (/\A\s*/).match(line)[0].length
211
+ indent_size = preceding_whitespace unless indent_size
212
+ if line === ''
213
+ ''
214
+ elsif (indent_size <= preceding_whitespace) && (indent_size > 0)
215
+ line[indent_size..line.length]
216
+ else
217
+ line
218
+ end
219
+ end
220
+ normalized.join("\n")
221
+ end
222
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dss
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matt Clough
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Documented Style Sheets
14
+ email: matt@mattclough.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/dss.rb
20
+ homepage:
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.6.7
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: A Ruby port of DSS by Darcy Clarke (https://github.com/DSSWG/DSS)
44
+ test_files: []