kss-rails 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -1
- data/Gemfile +0 -1
- data/app/assets/javascripts/kss.coffee +6 -6
- data/app/assets/javascripts/rainbow.js +858 -0
- data/app/assets/stylesheets/blackboard.css +63 -0
- data/app/assets/stylesheets/kss.css.scss +9 -42
- data/app/helpers/kss/application_helper.rb +5 -0
- data/app/views/kss/home/index.html.erb +1 -1
- data/app/views/kss/shared/_styleguide_block.erb +2 -0
- data/kss-rails.gemspec +6 -6
- data/lib/generators/templates/application.html.erb +6 -4
- data/lib/generators/templates/styleguide.html.erb +1 -10
- metadata +19 -7
data/CHANGELOG.md
CHANGED
@@ -4,4 +4,9 @@
|
|
4
4
|
|
5
5
|
# 1.0.1
|
6
6
|
|
7
|
-
* Added kss/application layout to the KSS::ApplicationController
|
7
|
+
* Added kss/application layout to the KSS::ApplicationController
|
8
|
+
|
9
|
+
# 1.0.2
|
10
|
+
|
11
|
+
* Highlight source code blocks (jankeesvw)
|
12
|
+
* Raise an error suggesting to find missing section if not found (jankeesvw)
|
data/Gemfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# This class scans your stylesheets for pseudo classes, then inserts a new CSS
|
2
2
|
# rule with the same properties, but named 'psuedo-class-{{name}}'.
|
3
3
|
#
|
4
|
-
# Supported pseudo classes: hover, disabled.
|
4
|
+
# Supported pseudo classes: hover, disabled, active, visited.
|
5
5
|
#
|
6
6
|
# Example:
|
7
7
|
#
|
@@ -9,16 +9,16 @@
|
|
9
9
|
# => a.pseudo-class-hover{ color:blue; }
|
10
10
|
class KssStateGenerator
|
11
11
|
constructor: ->
|
12
|
-
|
13
|
-
disabled = /:disabled/
|
14
|
-
active = /:active/
|
12
|
+
pseudos = /(\:hover|\:disabled|\:active|\:visited)/g
|
15
13
|
|
16
14
|
try
|
17
15
|
for stylesheet in document.styleSheets
|
18
16
|
idxs = []
|
19
17
|
for rule, idx in stylesheet.cssRules
|
20
|
-
if rule.type
|
21
|
-
|
18
|
+
if (rule.type == CSSRule.STYLE_RULE) && pseudos.test(rule.selectorText)
|
19
|
+
replaceRule = (matched, stuff) ->
|
20
|
+
return ".pseudo-class-" + matched.replace(':', '')
|
21
|
+
@insertRule(rule.cssText.replace(pseudos, replaceRule))
|
22
22
|
|
23
23
|
# Takes a given style and attaches it to the current page.
|
24
24
|
#
|
@@ -0,0 +1,858 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2012 Craig Campbell
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*
|
16
|
+
* Rainbow is a simple code syntax highlighter
|
17
|
+
*
|
18
|
+
* @preserve @version 1.1.8
|
19
|
+
* @url rainbowco.de
|
20
|
+
*/
|
21
|
+
window['Rainbow'] = (function() {
|
22
|
+
|
23
|
+
/**
|
24
|
+
* array of replacements to process at the end
|
25
|
+
*
|
26
|
+
* @type {Object}
|
27
|
+
*/
|
28
|
+
var replacements = {},
|
29
|
+
|
30
|
+
/**
|
31
|
+
* an array of start and end positions of blocks to be replaced
|
32
|
+
*
|
33
|
+
* @type {Object}
|
34
|
+
*/
|
35
|
+
replacement_positions = {},
|
36
|
+
|
37
|
+
/**
|
38
|
+
* an array of the language patterns specified for each language
|
39
|
+
*
|
40
|
+
* @type {Object}
|
41
|
+
*/
|
42
|
+
language_patterns = {},
|
43
|
+
|
44
|
+
/**
|
45
|
+
* an array of languages and whether they should bypass the default patterns
|
46
|
+
*
|
47
|
+
* @type {Object}
|
48
|
+
*/
|
49
|
+
bypass_defaults = {},
|
50
|
+
|
51
|
+
/**
|
52
|
+
* processing level
|
53
|
+
*
|
54
|
+
* replacements are stored at this level so if there is a sub block of code
|
55
|
+
* (for example php inside of html) it runs at a different level
|
56
|
+
*
|
57
|
+
* @type {number}
|
58
|
+
*/
|
59
|
+
CURRENT_LEVEL = 0,
|
60
|
+
|
61
|
+
/**
|
62
|
+
* constant used to refer to the default language
|
63
|
+
*
|
64
|
+
* @type {number}
|
65
|
+
*/
|
66
|
+
DEFAULT_LANGUAGE = 0,
|
67
|
+
|
68
|
+
/**
|
69
|
+
* used as counters so we can selectively call setTimeout
|
70
|
+
* after processing a certain number of matches/replacements
|
71
|
+
*
|
72
|
+
* @type {number}
|
73
|
+
*/
|
74
|
+
match_counter = 0,
|
75
|
+
|
76
|
+
/**
|
77
|
+
* @type {number}
|
78
|
+
*/
|
79
|
+
replacement_counter = 0,
|
80
|
+
|
81
|
+
/**
|
82
|
+
* @type {null|string}
|
83
|
+
*/
|
84
|
+
global_class,
|
85
|
+
|
86
|
+
/**
|
87
|
+
* @type {null|Function}
|
88
|
+
*/
|
89
|
+
onHighlight;
|
90
|
+
|
91
|
+
/**
|
92
|
+
* cross browser get attribute for an element
|
93
|
+
*
|
94
|
+
* @see http://stackoverflow.com/questions/3755227/cross-browser-javascript-getattribute-method
|
95
|
+
*
|
96
|
+
* @param {Node} el
|
97
|
+
* @param {string} attr attribute you are trying to get
|
98
|
+
* @returns {string|number}
|
99
|
+
*/
|
100
|
+
function _attr(el, attr, attrs, i) {
|
101
|
+
var result = (el.getAttribute && el.getAttribute(attr)) || 0;
|
102
|
+
|
103
|
+
if (!result) {
|
104
|
+
attrs = el.attributes;
|
105
|
+
|
106
|
+
for (i = 0; i < attrs.length; ++i) {
|
107
|
+
if (attrs[i].nodeName === attr) {
|
108
|
+
return attrs[i].nodeValue;
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
return result;
|
114
|
+
}
|
115
|
+
|
116
|
+
/**
|
117
|
+
* adds a class to a given code block
|
118
|
+
*
|
119
|
+
* @param {Element} el
|
120
|
+
* @param {string} class_name class name to add
|
121
|
+
* @returns void
|
122
|
+
*/
|
123
|
+
function _addClass(el, class_name) {
|
124
|
+
el.className += el.className ? ' ' + class_name : class_name;
|
125
|
+
}
|
126
|
+
|
127
|
+
/**
|
128
|
+
* checks if a block has a given class
|
129
|
+
*
|
130
|
+
* @param {Element} el
|
131
|
+
* @param {string} class_name class name to check for
|
132
|
+
* @returns {boolean}
|
133
|
+
*/
|
134
|
+
function _hasClass(el, class_name) {
|
135
|
+
return (' ' + el.className + ' ').indexOf(' ' + class_name + ' ') > -1;
|
136
|
+
}
|
137
|
+
|
138
|
+
/**
|
139
|
+
* gets the language for this block of code
|
140
|
+
*
|
141
|
+
* @param {Element} block
|
142
|
+
* @returns {string|null}
|
143
|
+
*/
|
144
|
+
function _getLanguageForBlock(block) {
|
145
|
+
|
146
|
+
// if this doesn't have a language but the parent does then use that
|
147
|
+
// this means if for example you have: <pre data-language="php">
|
148
|
+
// with a bunch of <code> blocks inside then you do not have
|
149
|
+
// to specify the language for each block
|
150
|
+
var language = _attr(block, 'data-language') || _attr(block.parentNode, 'data-language');
|
151
|
+
|
152
|
+
// this adds support for specifying language via a css class
|
153
|
+
// you can use the Google Code Prettify style: <pre class="lang-php">
|
154
|
+
// or the HTML5 style: <pre><code class="language-php">
|
155
|
+
if (!language) {
|
156
|
+
var pattern = /\blang(?:uage)?-(\w+)/,
|
157
|
+
match = block.className.match(pattern) || block.parentNode.className.match(pattern);
|
158
|
+
|
159
|
+
if (match) {
|
160
|
+
language = match[1];
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
return language;
|
165
|
+
}
|
166
|
+
|
167
|
+
/**
|
168
|
+
* makes sure html entities are always used for tags
|
169
|
+
*
|
170
|
+
* @param {string} code
|
171
|
+
* @returns {string}
|
172
|
+
*/
|
173
|
+
function _htmlEntities(code) {
|
174
|
+
return code.replace(/</g, '<').replace(/>/g, '>').replace(/&(?![\w\#]+;)/g, '&');
|
175
|
+
}
|
176
|
+
|
177
|
+
/**
|
178
|
+
* determines if a new match intersects with an existing one
|
179
|
+
*
|
180
|
+
* @param {number} start1 start position of existing match
|
181
|
+
* @param {number} end1 end position of existing match
|
182
|
+
* @param {number} start2 start position of new match
|
183
|
+
* @param {number} end2 end position of new match
|
184
|
+
* @returns {boolean}
|
185
|
+
*/
|
186
|
+
function _intersects(start1, end1, start2, end2) {
|
187
|
+
if (start2 >= start1 && start2 < end1) {
|
188
|
+
return true;
|
189
|
+
}
|
190
|
+
|
191
|
+
return end2 > start1 && end2 < end1;
|
192
|
+
}
|
193
|
+
|
194
|
+
/**
|
195
|
+
* determines if two different matches have complete overlap with each other
|
196
|
+
*
|
197
|
+
* @param {number} start1 start position of existing match
|
198
|
+
* @param {number} end1 end position of existing match
|
199
|
+
* @param {number} start2 start position of new match
|
200
|
+
* @param {number} end2 end position of new match
|
201
|
+
* @returns {boolean}
|
202
|
+
*/
|
203
|
+
function _hasCompleteOverlap(start1, end1, start2, end2) {
|
204
|
+
|
205
|
+
// if the starting and end positions are exactly the same
|
206
|
+
// then the first one should stay and this one should be ignored
|
207
|
+
if (start2 == start1 && end2 == end1) {
|
208
|
+
return false;
|
209
|
+
}
|
210
|
+
|
211
|
+
return start2 <= start1 && end2 >= end1;
|
212
|
+
}
|
213
|
+
|
214
|
+
/**
|
215
|
+
* determines if the match passed in falls inside of an existing match
|
216
|
+
* this prevents a regex pattern from matching inside of a bigger pattern
|
217
|
+
*
|
218
|
+
* @param {number} start - start position of new match
|
219
|
+
* @param {number} end - end position of new match
|
220
|
+
* @returns {boolean}
|
221
|
+
*/
|
222
|
+
function _matchIsInsideOtherMatch(start, end) {
|
223
|
+
for (var key in replacement_positions[CURRENT_LEVEL]) {
|
224
|
+
key = parseInt(key, 10);
|
225
|
+
|
226
|
+
// if this block completely overlaps with another block
|
227
|
+
// then we should remove the other block and return false
|
228
|
+
if (_hasCompleteOverlap(key, replacement_positions[CURRENT_LEVEL][key], start, end)) {
|
229
|
+
delete replacement_positions[CURRENT_LEVEL][key];
|
230
|
+
delete replacements[CURRENT_LEVEL][key];
|
231
|
+
}
|
232
|
+
|
233
|
+
if (_intersects(key, replacement_positions[CURRENT_LEVEL][key], start, end)) {
|
234
|
+
return true;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
return false;
|
239
|
+
}
|
240
|
+
|
241
|
+
/**
|
242
|
+
* takes a string of code and wraps it in a span tag based on the name
|
243
|
+
*
|
244
|
+
* @param {string} name name of the pattern (ie keyword.regex)
|
245
|
+
* @param {string} code block of code to wrap
|
246
|
+
* @returns {string}
|
247
|
+
*/
|
248
|
+
function _wrapCodeInSpan(name, code) {
|
249
|
+
return '<span class="' + name.replace(/\./g, ' ') + (global_class ? ' ' + global_class : '') + '">' + code + '</span>';
|
250
|
+
}
|
251
|
+
|
252
|
+
/**
|
253
|
+
* finds out the position of group match for a regular expression
|
254
|
+
*
|
255
|
+
* @see http://stackoverflow.com/questions/1985594/how-to-find-index-of-groups-in-match
|
256
|
+
*
|
257
|
+
* @param {Object} match
|
258
|
+
* @param {number} group_number
|
259
|
+
* @returns {number}
|
260
|
+
*/
|
261
|
+
function _indexOfGroup(match, group_number) {
|
262
|
+
var index = 0,
|
263
|
+
i;
|
264
|
+
|
265
|
+
for (i = 1; i < group_number; ++i) {
|
266
|
+
if (match[i]) {
|
267
|
+
index += match[i].length;
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
271
|
+
return index;
|
272
|
+
}
|
273
|
+
|
274
|
+
/**
|
275
|
+
* matches a regex pattern against a block of code
|
276
|
+
* finds all matches that should be processed and stores the positions
|
277
|
+
* of where they should be replaced within the string
|
278
|
+
*
|
279
|
+
* this is where pretty much all the work is done but it should not
|
280
|
+
* be called directly
|
281
|
+
*
|
282
|
+
* @param {RegExp} pattern
|
283
|
+
* @param {string} code
|
284
|
+
* @returns void
|
285
|
+
*/
|
286
|
+
function _processPattern(regex, pattern, code, callback)
|
287
|
+
{
|
288
|
+
var match = regex.exec(code);
|
289
|
+
|
290
|
+
if (!match) {
|
291
|
+
return callback();
|
292
|
+
}
|
293
|
+
|
294
|
+
++match_counter;
|
295
|
+
|
296
|
+
// treat match 0 the same way as name
|
297
|
+
if (!pattern['name'] && typeof pattern['matches'][0] == 'string') {
|
298
|
+
pattern['name'] = pattern['matches'][0];
|
299
|
+
delete pattern['matches'][0];
|
300
|
+
}
|
301
|
+
|
302
|
+
var replacement = match[0],
|
303
|
+
start_pos = match.index,
|
304
|
+
end_pos = match[0].length + start_pos,
|
305
|
+
|
306
|
+
/**
|
307
|
+
* callback to process the next match of this pattern
|
308
|
+
*/
|
309
|
+
processNext = function() {
|
310
|
+
var nextCall = function() {
|
311
|
+
_processPattern(regex, pattern, code, callback);
|
312
|
+
};
|
313
|
+
|
314
|
+
// every 100 items we process let's call set timeout
|
315
|
+
// to let the ui breathe a little
|
316
|
+
return match_counter % 100 > 0 ? nextCall() : setTimeout(nextCall, 0);
|
317
|
+
};
|
318
|
+
|
319
|
+
// if this is not a child match and it falls inside of another
|
320
|
+
// match that already happened we should skip it and continue processing
|
321
|
+
if (_matchIsInsideOtherMatch(start_pos, end_pos)) {
|
322
|
+
return processNext();
|
323
|
+
}
|
324
|
+
|
325
|
+
/**
|
326
|
+
* callback for when a match was successfully processed
|
327
|
+
*
|
328
|
+
* @param {string} replacement
|
329
|
+
* @returns void
|
330
|
+
*/
|
331
|
+
var onMatchSuccess = function(replacement) {
|
332
|
+
// if this match has a name then wrap it in a span tag
|
333
|
+
if (pattern['name']) {
|
334
|
+
replacement = _wrapCodeInSpan(pattern['name'], replacement);
|
335
|
+
}
|
336
|
+
|
337
|
+
// console.log('LEVEL', CURRENT_LEVEL, 'replace', match[0], 'with', replacement, 'at position', start_pos, 'to', end_pos);
|
338
|
+
|
339
|
+
// store what needs to be replaced with what at this position
|
340
|
+
if (!replacements[CURRENT_LEVEL]) {
|
341
|
+
replacements[CURRENT_LEVEL] = {};
|
342
|
+
replacement_positions[CURRENT_LEVEL] = {};
|
343
|
+
}
|
344
|
+
|
345
|
+
replacements[CURRENT_LEVEL][start_pos] = {
|
346
|
+
'replace': match[0],
|
347
|
+
'with': replacement
|
348
|
+
};
|
349
|
+
|
350
|
+
// store the range of this match so we can use it for comparisons
|
351
|
+
// with other matches later
|
352
|
+
replacement_positions[CURRENT_LEVEL][start_pos] = end_pos;
|
353
|
+
|
354
|
+
// process the next match
|
355
|
+
processNext();
|
356
|
+
},
|
357
|
+
|
358
|
+
// if this pattern has sub matches for different groups in the regex
|
359
|
+
// then we should process them one at a time by rerunning them through
|
360
|
+
// this function to generate the new replacement
|
361
|
+
//
|
362
|
+
// we run through them backwards because the match position of earlier
|
363
|
+
// matches will not change depending on what gets replaced in later
|
364
|
+
// matches
|
365
|
+
group_keys = keys(pattern['matches']),
|
366
|
+
|
367
|
+
/**
|
368
|
+
* callback for processing a sub group
|
369
|
+
*
|
370
|
+
* @param {number} i
|
371
|
+
* @param {Array} group_keys
|
372
|
+
* @param {Function} callback
|
373
|
+
*/
|
374
|
+
processGroup = function(i, group_keys, callback) {
|
375
|
+
if (i >= group_keys.length) {
|
376
|
+
return callback(replacement);
|
377
|
+
}
|
378
|
+
|
379
|
+
var processNextGroup = function() {
|
380
|
+
processGroup(++i, group_keys, callback);
|
381
|
+
},
|
382
|
+
block = match[group_keys[i]];
|
383
|
+
|
384
|
+
// if there is no match here then move on
|
385
|
+
if (!block) {
|
386
|
+
return processNextGroup();
|
387
|
+
}
|
388
|
+
|
389
|
+
var group = pattern['matches'][group_keys[i]],
|
390
|
+
language = group['language'],
|
391
|
+
|
392
|
+
/**
|
393
|
+
* process group is what group we should use to actually process
|
394
|
+
* this match group
|
395
|
+
*
|
396
|
+
* for example if the subgroup pattern looks like this
|
397
|
+
* 2: {
|
398
|
+
* 'name': 'keyword',
|
399
|
+
* 'pattern': /true/g
|
400
|
+
* }
|
401
|
+
*
|
402
|
+
* then we use that as is, but if it looks like this
|
403
|
+
*
|
404
|
+
* 2: {
|
405
|
+
* 'name': 'keyword',
|
406
|
+
* 'matches': {
|
407
|
+
* 'name': 'special',
|
408
|
+
* 'pattern': /whatever/g
|
409
|
+
* }
|
410
|
+
* }
|
411
|
+
*
|
412
|
+
* we treat the 'matches' part as the pattern and keep
|
413
|
+
* the name around to wrap it with later
|
414
|
+
*/
|
415
|
+
process_group = group['name'] && group['matches'] ? group['matches'] : group,
|
416
|
+
|
417
|
+
/**
|
418
|
+
* takes the code block matched at this group, replaces it
|
419
|
+
* with the highlighted block, and optionally wraps it with
|
420
|
+
* a span with a name
|
421
|
+
*
|
422
|
+
* @param {string} block
|
423
|
+
* @param {string} replace_block
|
424
|
+
* @param {string|null} match_name
|
425
|
+
*/
|
426
|
+
_replaceAndContinue = function(block, replace_block, match_name) {
|
427
|
+
replacement = _replaceAtPosition(_indexOfGroup(match, group_keys[i]), block, match_name ? _wrapCodeInSpan(match_name, replace_block) : replace_block, replacement);
|
428
|
+
processNextGroup();
|
429
|
+
};
|
430
|
+
|
431
|
+
// if this is a sublanguage go and process the block using that language
|
432
|
+
if (language) {
|
433
|
+
return _highlightBlockForLanguage(block, language, function(code) {
|
434
|
+
_replaceAndContinue(block, code);
|
435
|
+
});
|
436
|
+
}
|
437
|
+
|
438
|
+
// if this is a string then this match is directly mapped to selector
|
439
|
+
// so all we have to do is wrap it in a span and continue
|
440
|
+
if (typeof group === 'string') {
|
441
|
+
return _replaceAndContinue(block, block, group);
|
442
|
+
}
|
443
|
+
|
444
|
+
// the process group can be a single pattern or an array of patterns
|
445
|
+
// _processCodeWithPatterns always expects an array so we convert it here
|
446
|
+
_processCodeWithPatterns(block, process_group.length ? process_group : [process_group], function(code) {
|
447
|
+
_replaceAndContinue(block, code, group['matches'] ? group['name'] : 0);
|
448
|
+
});
|
449
|
+
};
|
450
|
+
|
451
|
+
processGroup(0, group_keys, onMatchSuccess);
|
452
|
+
}
|
453
|
+
|
454
|
+
/**
|
455
|
+
* should a language bypass the default patterns?
|
456
|
+
*
|
457
|
+
* if you call Rainbow.extend() and pass true as the third argument
|
458
|
+
* it will bypass the defaults
|
459
|
+
*/
|
460
|
+
function _bypassDefaultPatterns(language)
|
461
|
+
{
|
462
|
+
return bypass_defaults[language];
|
463
|
+
}
|
464
|
+
|
465
|
+
/**
|
466
|
+
* returns a list of regex patterns for this language
|
467
|
+
*
|
468
|
+
* @param {string} language
|
469
|
+
* @returns {Array}
|
470
|
+
*/
|
471
|
+
function _getPatternsForLanguage(language) {
|
472
|
+
var patterns = language_patterns[language] || [],
|
473
|
+
default_patterns = language_patterns[DEFAULT_LANGUAGE] || [];
|
474
|
+
|
475
|
+
return _bypassDefaultPatterns(language) ? patterns : patterns.concat(default_patterns);
|
476
|
+
}
|
477
|
+
|
478
|
+
/**
|
479
|
+
* substring replace call to replace part of a string at a certain position
|
480
|
+
*
|
481
|
+
* @param {number} position the position where the replacement should happen
|
482
|
+
* @param {string} replace the text we want to replace
|
483
|
+
* @param {string} replace_with the text we want to replace it with
|
484
|
+
* @param {string} code the code we are doing the replacing in
|
485
|
+
* @returns {string}
|
486
|
+
*/
|
487
|
+
function _replaceAtPosition(position, replace, replace_with, code) {
|
488
|
+
var sub_string = code.substr(position);
|
489
|
+
return code.substr(0, position) + sub_string.replace(replace, replace_with);
|
490
|
+
}
|
491
|
+
|
492
|
+
/**
|
493
|
+
* sorts an object by index descending
|
494
|
+
*
|
495
|
+
* @param {Object} object
|
496
|
+
* @return {Array}
|
497
|
+
*/
|
498
|
+
function keys(object) {
|
499
|
+
var locations = [],
|
500
|
+
replacement,
|
501
|
+
pos;
|
502
|
+
|
503
|
+
for(var location in object) {
|
504
|
+
if (object.hasOwnProperty(location)) {
|
505
|
+
locations.push(location);
|
506
|
+
}
|
507
|
+
}
|
508
|
+
|
509
|
+
// numeric descending
|
510
|
+
return locations.sort(function(a, b) {
|
511
|
+
return b - a;
|
512
|
+
});
|
513
|
+
}
|
514
|
+
|
515
|
+
/**
|
516
|
+
* processes a block of code using specified patterns
|
517
|
+
*
|
518
|
+
* @param {string} code
|
519
|
+
* @param {Array} patterns
|
520
|
+
* @returns void
|
521
|
+
*/
|
522
|
+
function _processCodeWithPatterns(code, patterns, callback)
|
523
|
+
{
|
524
|
+
// we have to increase the level here so that the
|
525
|
+
// replacements will not conflict with each other when
|
526
|
+
// processing sub blocks of code
|
527
|
+
++CURRENT_LEVEL;
|
528
|
+
|
529
|
+
// patterns are processed one at a time through this function
|
530
|
+
function _workOnPatterns(patterns, i)
|
531
|
+
{
|
532
|
+
// still have patterns to process, keep going
|
533
|
+
if (i < patterns.length) {
|
534
|
+
return _processPattern(patterns[i]['pattern'], patterns[i], code, function() {
|
535
|
+
_workOnPatterns(patterns, ++i);
|
536
|
+
});
|
537
|
+
}
|
538
|
+
|
539
|
+
// we are done processing the patterns
|
540
|
+
// process the replacements and update the DOM
|
541
|
+
_processReplacements(code, function(code) {
|
542
|
+
|
543
|
+
// when we are done processing replacements
|
544
|
+
// we are done at this level so we can go back down
|
545
|
+
delete replacements[CURRENT_LEVEL];
|
546
|
+
delete replacement_positions[CURRENT_LEVEL];
|
547
|
+
--CURRENT_LEVEL;
|
548
|
+
callback(code);
|
549
|
+
});
|
550
|
+
}
|
551
|
+
|
552
|
+
_workOnPatterns(patterns, 0);
|
553
|
+
}
|
554
|
+
|
555
|
+
/**
|
556
|
+
* process replacements in the string of code to actually update the markup
|
557
|
+
*
|
558
|
+
* @param {string} code the code to process replacements in
|
559
|
+
* @param {Function} onComplete what to do when we are done processing
|
560
|
+
* @returns void
|
561
|
+
*/
|
562
|
+
function _processReplacements(code, onComplete) {
|
563
|
+
|
564
|
+
/**
|
565
|
+
* processes a single replacement
|
566
|
+
*
|
567
|
+
* @param {string} code
|
568
|
+
* @param {Array} positions
|
569
|
+
* @param {number} i
|
570
|
+
* @param {Function} onComplete
|
571
|
+
* @returns void
|
572
|
+
*/
|
573
|
+
function _processReplacement(code, positions, i, onComplete) {
|
574
|
+
if (i < positions.length) {
|
575
|
+
++replacement_counter;
|
576
|
+
var pos = positions[i],
|
577
|
+
replacement = replacements[CURRENT_LEVEL][pos];
|
578
|
+
code = _replaceAtPosition(pos, replacement['replace'], replacement['with'], code);
|
579
|
+
|
580
|
+
// process next function
|
581
|
+
var next = function() {
|
582
|
+
_processReplacement(code, positions, ++i, onComplete);
|
583
|
+
};
|
584
|
+
|
585
|
+
// use a timeout every 250 to not freeze up the UI
|
586
|
+
return replacement_counter % 250 > 0 ? next() : setTimeout(next, 0);
|
587
|
+
}
|
588
|
+
|
589
|
+
onComplete(code);
|
590
|
+
}
|
591
|
+
|
592
|
+
var string_positions = keys(replacements[CURRENT_LEVEL]);
|
593
|
+
_processReplacement(code, string_positions, 0, onComplete);
|
594
|
+
}
|
595
|
+
|
596
|
+
/**
|
597
|
+
* takes a string of code and highlights it according to the language specified
|
598
|
+
*
|
599
|
+
* @param {string} code
|
600
|
+
* @param {string} language
|
601
|
+
* @param {Function} onComplete
|
602
|
+
* @returns void
|
603
|
+
*/
|
604
|
+
function _highlightBlockForLanguage(code, language, onComplete) {
|
605
|
+
var patterns = _getPatternsForLanguage(language);
|
606
|
+
_processCodeWithPatterns(_htmlEntities(code), patterns, onComplete);
|
607
|
+
}
|
608
|
+
|
609
|
+
/**
|
610
|
+
* highlight an individual code block
|
611
|
+
*
|
612
|
+
* @param {Array} code_blocks
|
613
|
+
* @param {number} i
|
614
|
+
* @returns void
|
615
|
+
*/
|
616
|
+
function _highlightCodeBlock(code_blocks, i, onComplete) {
|
617
|
+
if (i < code_blocks.length) {
|
618
|
+
var block = code_blocks[i],
|
619
|
+
language = _getLanguageForBlock(block);
|
620
|
+
|
621
|
+
if (!_hasClass(block, 'rainbow') && language) {
|
622
|
+
language = language.toLowerCase();
|
623
|
+
|
624
|
+
_addClass(block, 'rainbow');
|
625
|
+
|
626
|
+
return _highlightBlockForLanguage(block.innerHTML, language, function(code) {
|
627
|
+
block.innerHTML = code;
|
628
|
+
|
629
|
+
// reset the replacement arrays
|
630
|
+
replacements = {};
|
631
|
+
replacement_positions = {};
|
632
|
+
|
633
|
+
// if you have a listener attached tell it that this block is now highlighted
|
634
|
+
if (onHighlight) {
|
635
|
+
onHighlight(block, language);
|
636
|
+
}
|
637
|
+
|
638
|
+
// process the next block
|
639
|
+
setTimeout(function() {
|
640
|
+
_highlightCodeBlock(code_blocks, ++i, onComplete);
|
641
|
+
}, 0);
|
642
|
+
});
|
643
|
+
}
|
644
|
+
return _highlightCodeBlock(code_blocks, ++i, onComplete);
|
645
|
+
}
|
646
|
+
|
647
|
+
if (onComplete) {
|
648
|
+
onComplete();
|
649
|
+
}
|
650
|
+
}
|
651
|
+
|
652
|
+
/**
|
653
|
+
* start highlighting all the code blocks
|
654
|
+
*
|
655
|
+
* @returns void
|
656
|
+
*/
|
657
|
+
function _highlight(node, onComplete) {
|
658
|
+
|
659
|
+
// the first argument can be an Event or a DOM Element
|
660
|
+
// I was originally checking instanceof Event but that makes it break
|
661
|
+
// when using mootools
|
662
|
+
//
|
663
|
+
// @see https://github.com/ccampbell/rainbow/issues/32
|
664
|
+
//
|
665
|
+
node = node && typeof node.getElementsByTagName == 'function' ? node : document;
|
666
|
+
|
667
|
+
var pre_blocks = node.getElementsByTagName('pre'),
|
668
|
+
code_blocks = node.getElementsByTagName('code'),
|
669
|
+
i,
|
670
|
+
final_blocks = [];
|
671
|
+
|
672
|
+
// @see http://stackoverflow.com/questions/2735067/how-to-convert-a-dom-node-list-to-an-array-in-javascript
|
673
|
+
// we are going to process all <code> blocks
|
674
|
+
for (i = 0; i < code_blocks.length; ++i) {
|
675
|
+
final_blocks.push(code_blocks[i]);
|
676
|
+
}
|
677
|
+
|
678
|
+
// loop through the pre blocks to see which ones we should add
|
679
|
+
for (i = 0; i < pre_blocks.length; ++i) {
|
680
|
+
|
681
|
+
// if the pre block has no code blocks then process it directly
|
682
|
+
if (!pre_blocks[i].getElementsByTagName('code').length) {
|
683
|
+
final_blocks.push(pre_blocks[i]);
|
684
|
+
}
|
685
|
+
}
|
686
|
+
|
687
|
+
_highlightCodeBlock(final_blocks, 0, onComplete);
|
688
|
+
}
|
689
|
+
|
690
|
+
/**
|
691
|
+
* public methods
|
692
|
+
*/
|
693
|
+
return {
|
694
|
+
|
695
|
+
/**
|
696
|
+
* extends the language pattern matches
|
697
|
+
*
|
698
|
+
* @param {*} language name of language
|
699
|
+
* @param {*} patterns array of patterns to add on
|
700
|
+
* @param {boolean|null} bypass if true this will bypass the default language patterns
|
701
|
+
*/
|
702
|
+
extend: function(language, patterns, bypass) {
|
703
|
+
|
704
|
+
// if there is only one argument then we assume that we want to
|
705
|
+
// extend the default language rules
|
706
|
+
if (arguments.length == 1) {
|
707
|
+
patterns = language;
|
708
|
+
language = DEFAULT_LANGUAGE;
|
709
|
+
}
|
710
|
+
|
711
|
+
bypass_defaults[language] = bypass;
|
712
|
+
language_patterns[language] = patterns.concat(language_patterns[language] || []);
|
713
|
+
},
|
714
|
+
|
715
|
+
/**
|
716
|
+
* call back to let you do stuff in your app after a piece of code has been highlighted
|
717
|
+
*
|
718
|
+
* @param {Function} callback
|
719
|
+
*/
|
720
|
+
onHighlight: function(callback) {
|
721
|
+
onHighlight = callback;
|
722
|
+
},
|
723
|
+
|
724
|
+
/**
|
725
|
+
* method to set a global class that will be applied to all spans
|
726
|
+
*
|
727
|
+
* @param {string} class_name
|
728
|
+
*/
|
729
|
+
addClass: function(class_name) {
|
730
|
+
global_class = class_name;
|
731
|
+
},
|
732
|
+
|
733
|
+
/**
|
734
|
+
* starts the magic rainbow
|
735
|
+
*
|
736
|
+
* @returns void
|
737
|
+
*/
|
738
|
+
color: function() {
|
739
|
+
|
740
|
+
// if you want to straight up highlight a string you can pass the string of code,
|
741
|
+
// the language, and a callback function
|
742
|
+
if (typeof arguments[0] == 'string') {
|
743
|
+
return _highlightBlockForLanguage(arguments[0], arguments[1], arguments[2]);
|
744
|
+
}
|
745
|
+
|
746
|
+
// if you pass a callback function then we rerun the color function
|
747
|
+
// on all the code and call the callback function on complete
|
748
|
+
if (typeof arguments[0] == 'function') {
|
749
|
+
return _highlight(0, arguments[0]);
|
750
|
+
}
|
751
|
+
|
752
|
+
// otherwise we use whatever node you passed in with an optional
|
753
|
+
// callback function as the second parameter
|
754
|
+
_highlight(arguments[0], arguments[1]);
|
755
|
+
}
|
756
|
+
};
|
757
|
+
}) ();
|
758
|
+
|
759
|
+
/**
|
760
|
+
* adds event listener to start highlighting
|
761
|
+
*/
|
762
|
+
(function() {
|
763
|
+
if (window.addEventListener) {
|
764
|
+
return window.addEventListener('load', Rainbow.color, false);
|
765
|
+
}
|
766
|
+
window.attachEvent('onload', Rainbow.color);
|
767
|
+
}) ();
|
768
|
+
|
769
|
+
// When using Google closure compiler in advanced mode some methods
|
770
|
+
// get renamed. This keeps a public reference to these methods so they can
|
771
|
+
// still be referenced from outside this library.
|
772
|
+
Rainbow["onHighlight"] = Rainbow.onHighlight;
|
773
|
+
Rainbow["addClass"] = Rainbow.addClass;
|
774
|
+
|
775
|
+
/**
|
776
|
+
* HTML patterns
|
777
|
+
*
|
778
|
+
* @author Craig Campbell
|
779
|
+
* @version 1.0.7
|
780
|
+
*/
|
781
|
+
Rainbow.extend('html', [
|
782
|
+
{
|
783
|
+
'name': 'source.php.embedded',
|
784
|
+
'matches': {
|
785
|
+
2: {
|
786
|
+
'language': 'php'
|
787
|
+
}
|
788
|
+
},
|
789
|
+
'pattern': /<\?=?(?!xml)(php)?([\s\S]*?)(\?>)/gm
|
790
|
+
},
|
791
|
+
{
|
792
|
+
'name': 'source.css.embedded',
|
793
|
+
'matches': {
|
794
|
+
0: {
|
795
|
+
'language': 'css'
|
796
|
+
}
|
797
|
+
},
|
798
|
+
'pattern': /<style(.*?)>([\s\S]*?)<\/style>/gm
|
799
|
+
},
|
800
|
+
{
|
801
|
+
'name': 'source.js.embedded',
|
802
|
+
'matches': {
|
803
|
+
0: {
|
804
|
+
'language': 'javascript'
|
805
|
+
}
|
806
|
+
},
|
807
|
+
'pattern': /<script(?! src)(.*?)>([\s\S]*?)<\/script>/gm
|
808
|
+
},
|
809
|
+
{
|
810
|
+
'name': 'comment.html',
|
811
|
+
'pattern': /<\!--[\S\s]*?-->/g
|
812
|
+
},
|
813
|
+
{
|
814
|
+
'matches': {
|
815
|
+
1: 'support.tag.open',
|
816
|
+
2: 'support.tag.close'
|
817
|
+
},
|
818
|
+
'pattern': /(<)|(\/?\??>)/g
|
819
|
+
},
|
820
|
+
{
|
821
|
+
'name': 'support.tag',
|
822
|
+
'matches': {
|
823
|
+
1: 'support.tag',
|
824
|
+
2: 'support.tag.special',
|
825
|
+
3: 'support.tag-name'
|
826
|
+
},
|
827
|
+
'pattern': /(<\??)(\/|\!?)(\w+)/g
|
828
|
+
},
|
829
|
+
{
|
830
|
+
'matches': {
|
831
|
+
1: 'support.attribute'
|
832
|
+
},
|
833
|
+
'pattern': /([a-z-]+)(?=\=)/gi
|
834
|
+
},
|
835
|
+
{
|
836
|
+
'matches': {
|
837
|
+
1: 'support.operator',
|
838
|
+
2: 'string.quote',
|
839
|
+
3: 'string.value',
|
840
|
+
4: 'string.quote'
|
841
|
+
},
|
842
|
+
'pattern': /(=)('|")(.*?)(\2)/g
|
843
|
+
},
|
844
|
+
{
|
845
|
+
'matches': {
|
846
|
+
1: 'support.operator',
|
847
|
+
2: 'support.value'
|
848
|
+
},
|
849
|
+
'pattern': /(=)([a-zA-Z\-0-9]*)\b/g
|
850
|
+
},
|
851
|
+
{
|
852
|
+
'matches': {
|
853
|
+
1: 'support.attribute'
|
854
|
+
},
|
855
|
+
'pattern': /\s(\w+)(?=\s|>)(?![\s\S]*<)/g
|
856
|
+
}
|
857
|
+
], true);
|
858
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/**
|
2
|
+
* Blackboard theme
|
3
|
+
*
|
4
|
+
* Adapted from Domenico Carbotta's TextMate theme of the same name
|
5
|
+
*
|
6
|
+
* @author Domenico Carbotta
|
7
|
+
* @author Craig Campbell
|
8
|
+
* @version 1.0.2
|
9
|
+
*/
|
10
|
+
pre {
|
11
|
+
background: #0B1022;
|
12
|
+
word-wrap: break-word;
|
13
|
+
margin: 0px;
|
14
|
+
padding: 0px;
|
15
|
+
padding: 10px;
|
16
|
+
color: #fff;
|
17
|
+
font-size: 14px;
|
18
|
+
margin-bottom: 20px;
|
19
|
+
}
|
20
|
+
|
21
|
+
pre, code {
|
22
|
+
font-family: 'Monaco', courier, monospace;
|
23
|
+
}
|
24
|
+
|
25
|
+
pre .comment {
|
26
|
+
color: #727272;
|
27
|
+
}
|
28
|
+
|
29
|
+
pre .constant {
|
30
|
+
color: #D8FA3C;
|
31
|
+
}
|
32
|
+
|
33
|
+
pre .storage {
|
34
|
+
color: #FBDE2D;
|
35
|
+
}
|
36
|
+
|
37
|
+
pre .string, pre .comment.docstring {
|
38
|
+
color: #61CE3C;
|
39
|
+
}
|
40
|
+
|
41
|
+
pre .string.regexp, pre .support.tag.script, pre .support.tag.style {
|
42
|
+
color: #fff;
|
43
|
+
}
|
44
|
+
|
45
|
+
pre .keyword, pre .selector {
|
46
|
+
color: #FBDE2D;
|
47
|
+
}
|
48
|
+
|
49
|
+
pre .inherited-class {
|
50
|
+
font-style: italic;
|
51
|
+
}
|
52
|
+
|
53
|
+
pre .entity {
|
54
|
+
color: #FF6400;
|
55
|
+
}
|
56
|
+
|
57
|
+
pre .support, *[data-language="c"] .function.call {
|
58
|
+
color: #8DA6CE;
|
59
|
+
}
|
60
|
+
|
61
|
+
pre .variable.global, pre .variable.class, pre .variable.instance {
|
62
|
+
color: #FF6400;
|
63
|
+
}
|
@@ -1,39 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
----------------------------------------------------------------------------*/
|
4
|
-
* {
|
5
|
-
padding:0;
|
6
|
-
margin:0;
|
7
|
-
}
|
8
|
-
h1, h2, h3, h4, h5, h6, p, pre, blockquote, label, ul, ol, dl, fieldset, address { margin:1em 0; }
|
9
|
-
li, dd { margin-left:5%; }
|
10
|
-
fieldset { padding: .5em; }
|
11
|
-
select option{ padding:0 5px; }
|
12
|
-
|
13
|
-
.access{ display:none; } /* For accessibility related elements */
|
14
|
-
.clear{ clear:both; height:0px; font-size:0px; line-height:0px; overflow:hidden; }
|
15
|
-
a{ outline:none; }
|
16
|
-
a img{ border:none; }
|
17
|
-
|
18
|
-
.clearfix:after {
|
19
|
-
content: ".";
|
20
|
-
display: block;
|
21
|
-
height: 0;
|
22
|
-
clear: both;
|
23
|
-
visibility: hidden;
|
1
|
+
.kss-body {
|
2
|
+
margin: 0;
|
24
3
|
}
|
25
|
-
* html .clearfix {height: 1%;}
|
26
|
-
.clearfix {display:inline-block;}
|
27
|
-
.clearfix {display: block;}
|
28
|
-
|
29
|
-
/* @end */
|
30
4
|
|
31
|
-
|
32
|
-
font-family:Helvetica, Arial, sans-serif;
|
33
|
-
font-size:14px;
|
34
|
-
}
|
35
|
-
|
36
|
-
header{
|
5
|
+
.kss-header{
|
37
6
|
padding:10px;
|
38
7
|
|
39
8
|
font-size:16px;
|
@@ -43,24 +12,24 @@ header{
|
|
43
12
|
border-bottom:1px solid #ddd;
|
44
13
|
}
|
45
14
|
|
46
|
-
#
|
15
|
+
#kss_wrapper{
|
47
16
|
padding-left:200px;
|
48
17
|
padding-right: 25px;
|
49
18
|
}
|
50
19
|
|
51
|
-
nav
|
20
|
+
nav.kss-nav{
|
52
21
|
float:left;
|
53
22
|
margin-left:-200px;
|
54
23
|
width:160px;
|
55
24
|
}
|
56
|
-
nav
|
25
|
+
nav.kss-nav>ul{
|
57
26
|
margin-left:10px;
|
58
27
|
}
|
59
|
-
nav
|
28
|
+
nav.kss-nav>ul>li{
|
60
29
|
list-style-type:none;
|
61
30
|
margin:10px 0;
|
62
31
|
}
|
63
|
-
nav
|
32
|
+
nav.kss-nav>ul>li>a{
|
64
33
|
text-decoration:none;
|
65
34
|
color:#666;
|
66
35
|
}
|
@@ -137,6 +106,4 @@ h1.styleguide {
|
|
137
106
|
font-weight: normal;
|
138
107
|
color: #222; }
|
139
108
|
|
140
|
-
/* @end */
|
141
|
-
|
142
|
-
//= require application
|
109
|
+
/* @end */
|
@@ -7,6 +7,11 @@ module Kss
|
|
7
7
|
raise ArgumentError, "Missing block" unless block_given?
|
8
8
|
|
9
9
|
@section = styleguide.section(section)
|
10
|
+
|
11
|
+
if !@section.raw
|
12
|
+
raise "KSS styleguide section is nil, is section '#{section}' defined in your css?"
|
13
|
+
end
|
14
|
+
|
10
15
|
content = capture(&block)
|
11
16
|
render 'kss/shared/styleguide_block', :section => @section, :example_html => content
|
12
17
|
end
|
@@ -1,2 +1,2 @@
|
|
1
1
|
<h1>Welcome!</h1>
|
2
|
-
<p>This is an example <a href="
|
2
|
+
<p>This is an example <a href="./styleguide">styleguide</a>. To customize this page, create a file at <code>app/views/kss/home/index.html.erb</code>.</p>
|
@@ -13,10 +13,12 @@
|
|
13
13
|
<div class="styleguide-element">
|
14
14
|
<%= example_html.html_safe %>
|
15
15
|
</div>
|
16
|
+
<pre><code data-language="html"><%= example_html.strip %></code></pre>
|
16
17
|
<% section.modifiers.each do |modifier| %>
|
17
18
|
<div class="styleguide-element styleguide-modifier">
|
18
19
|
<span class="styleguide-modifier-name"><%= modifier.name %></span>
|
19
20
|
<%= example_html.gsub('$modifier_class', modifier.class_name).html_safe %>
|
20
21
|
</div>
|
22
|
+
<pre><code data-language="html"><%= example_html.gsub('$modifier_class', modifier.class_name).strip %></code></pre>
|
21
23
|
<% end %>
|
22
24
|
</div>
|
data/kss-rails.gemspec
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |gem|
|
3
|
-
gem.authors = [
|
4
|
-
gem.email = [
|
3
|
+
gem.authors = ['Garrett Bjerkhoel']
|
4
|
+
gem.email = ['me@garrettbjerkhoel.com']
|
5
5
|
gem.description = %q{Rails 3 engine to provide a living styleguide from Kyle Neath's KSS.}
|
6
6
|
gem.summary = %q{Rails 3 engine to provide a living styleguide from Kyle Neath's KSS.}
|
7
|
-
gem.homepage =
|
7
|
+
gem.homepage = 'https://github.com/dewski/kss-rails'
|
8
8
|
|
9
9
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
10
10
|
gem.files = `git ls-files`.split("\n")
|
11
11
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
12
|
-
gem.name =
|
13
|
-
gem.require_paths = [
|
14
|
-
gem.version = '1.0.
|
12
|
+
gem.name = 'kss-rails'
|
13
|
+
gem.require_paths = ['lib']
|
14
|
+
gem.version = '1.0.2'
|
15
15
|
|
16
16
|
gem.add_dependency 'kss'
|
17
17
|
gem.add_dependency 'rails', '>= 3.0.0'
|
@@ -5,15 +5,16 @@
|
|
5
5
|
<title>KSS Styleguide</title>
|
6
6
|
<%= stylesheet_link_tag 'kss' %>
|
7
7
|
<%= stylesheet_link_tag 'application' %>
|
8
|
+
<%= stylesheet_link_tag 'blackboard' %>
|
8
9
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
9
10
|
</head>
|
10
|
-
<body>
|
11
|
-
<header>
|
11
|
+
<body class="kss-body">
|
12
|
+
<header class="kss-header">
|
12
13
|
KSS Styleguide Example
|
13
14
|
</header>
|
14
15
|
|
15
|
-
<div id="
|
16
|
-
<nav role="main">
|
16
|
+
<div id="kss_wrapper">
|
17
|
+
<nav role="main" class="kss-nav">
|
17
18
|
<ul>
|
18
19
|
<li><%= link_to 'Home', kss.root_path %></li>
|
19
20
|
<li><%= link_to 'Styleguide', kss.styleguide_path %></li>
|
@@ -24,5 +25,6 @@
|
|
24
25
|
</div><!-- /#wrapper -->
|
25
26
|
|
26
27
|
<%= javascript_include_tag 'kss' %>
|
28
|
+
<%= javascript_include_tag 'rainbow' %>
|
27
29
|
</body>
|
28
30
|
</html>
|
@@ -1,12 +1,3 @@
|
|
1
1
|
<%= styleguide_block '1.1' do -%>
|
2
2
|
<button class="$modifier_class">Example Button</button>
|
3
|
-
<% end -%>
|
4
|
-
<p>This block above was created with a simple template call:</p>
|
5
|
-
<pre><code><%= styleguide_block '1.1' do %>
|
6
|
-
<button class="$modifier_class">Example Button</button>
|
7
|
-
<% end %></code></pre>
|
8
|
-
<p>
|
9
|
-
Take a look at the source code of this Rails engine for more details. The goal
|
10
|
-
is to remove the pain from creating a styleguide — document your CSS, have
|
11
|
-
example HTML in your templates and automate as much as possible.
|
12
|
-
</p>
|
3
|
+
<% end -%>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kss-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: kss
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rails
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,7 +37,12 @@ dependencies:
|
|
32
37
|
version: 3.0.0
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.0.0
|
36
46
|
description: Rails 3 engine to provide a living styleguide from Kyle Neath's KSS.
|
37
47
|
email:
|
38
48
|
- me@garrettbjerkhoel.com
|
@@ -47,6 +57,8 @@ files:
|
|
47
57
|
- README.md
|
48
58
|
- Rakefile
|
49
59
|
- app/assets/javascripts/kss.coffee
|
60
|
+
- app/assets/javascripts/rainbow.js
|
61
|
+
- app/assets/stylesheets/blackboard.css
|
50
62
|
- app/assets/stylesheets/kss.css.scss
|
51
63
|
- app/controllers/kss/application_controller.rb
|
52
64
|
- app/controllers/kss/home_controller.rb
|
@@ -81,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
93
|
version: '0'
|
82
94
|
requirements: []
|
83
95
|
rubyforge_project:
|
84
|
-
rubygems_version: 1.8.
|
96
|
+
rubygems_version: 1.8.23
|
85
97
|
signing_key:
|
86
98
|
specification_version: 3
|
87
99
|
summary: Rails 3 engine to provide a living styleguide from Kyle Neath's KSS.
|