Skip to content

Commit

Permalink
Allow string input for Kss::Parser
Browse files Browse the repository at this point in the history
Allowing string input (with `Kss::Parser.new(string)`) allows dynamic use cases in live web applications

Example:

```ruby
buttons =<<-'EOS'
  /*
  Your standard form button.

  :hover    - Highlights when hovering.
  :disabled - Dims the button when disabled.

  Styleguide 1.1
  */
  button {
    padding: 5px 15px;
    line-height: normal;
    font-family: "Helvetica Neue", Helvetica;
    font-size: 12px;
    font-weight: bold;
    color: #666;
    text-shadow: 0 1px rgba(255, 255, 255, 0.9);
    border-radius: 3px;
    border: 1px solid #ddd;
    border-bottom-color: #bbb;
    background: #f5f5f5;
    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='$start', endColorstr='$end');
    background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e5e5e5));
    background: -moz-linear-gradient(top, #f5f5f5, #e5e5e5);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
    cursor: pointer;
  }
  button:disabled {
    opacity: 0.5;
  }
EOS
@styleguide = Kss::Parser.new(buttons)
```

We can then imagine a web app for prototyping designs or html components that would provide live kss documentation & demo rendering without relying on static files.
  • Loading branch information
Jean-Paul Bonnetouche authored and goodtouch committed Jun 20, 2013
1 parent 96d2ef0 commit 73cdd12
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 51 deletions.
88 changes: 49 additions & 39 deletions lib/kss/comment_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,19 @@ def self.parse_multi_line(line)
# Public: Initializes a new comment parser object. Does not parse on
# initialization.
#
# file_path - The location of the file to parse as a String.
# options - Optional options hash.
# file_path_or_string_input - The location of the file to parse as a String, or the String itself.
# options - Optional options hash.
# :preserve_whitespace - Preserve the whitespace before/after comment
# markers (default:false).
#
def initialize(file_path, options={})
def initialize(file_path_or_string_input, options={})
@options = options
@options[:preserve_whitespace] = false if @options[:preserve_whitespace].nil?
@file_path = file_path
if File.exists?(file_path_or_string_input)
@file_path = file_path_or_string_input
else
@string_input = file_path_or_string_input
end
@blocks = []
@parsed = false
end
Expand All @@ -80,52 +84,58 @@ def blocks
@parsed ? @blocks : parse_blocks
end


# Parse the file for comment blocks and populate them into @blocks.
#
# Returns an Array of parsed comment Strings.
def parse_blocks
File.open @file_path do |file|
current_block = nil
inside_single_line_block = false
inside_multi_line_block = false

file.each_line do |line|
# Parse single-line style
if self.class.single_line_comment?(line)
parsed = self.class.parse_single_line line
if inside_single_line_block
current_block += "\n#{parsed}"
else
current_block = parsed.to_s
inside_single_line_block = true
end
if !@file_path.nil?
File.open @file_path do |file|
parse_blocks_input(file)
end
else
parse_blocks_input(@string_input)
end
end

def parse_blocks_input(input)
current_block = nil
inside_single_line_block = false
inside_multi_line_block = false

input.each_line do |line|
# Parse single-line style
if self.class.single_line_comment?(line)
parsed = self.class.parse_single_line line
if inside_single_line_block
current_block += "\n#{parsed}"
else
current_block = parsed.to_s
inside_single_line_block = true
end
end

# Parse multi-lines tyle
if self.class.start_multi_line_comment?(line) || inside_multi_line_block
parsed = self.class.parse_multi_line line
if inside_multi_line_block
current_block += "\n#{parsed}"
else
current_block = parsed
inside_multi_line_block = true
end
# Parse multi-lines tyle
if self.class.start_multi_line_comment?(line) || inside_multi_line_block
parsed = self.class.parse_multi_line line
if inside_multi_line_block
current_block += "\n#{parsed}"
else
current_block = parsed
inside_multi_line_block = true
end
end

# End a multi-line block if detected
inside_multi_line_block = false if self.class.end_multi_line_comment?(line)
# End a multi-line block if detected
inside_multi_line_block = false if self.class.end_multi_line_comment?(line)

# Store the current block if we're done
unless self.class.single_line_comment?(line) || inside_multi_line_block
@blocks << normalize(current_block) unless current_block.nil?
# Store the current block if we're done
unless self.class.single_line_comment?(line) || inside_multi_line_block
@blocks << normalize(current_block) unless current_block.nil?

inside_single_line_block = false
current_block = nil
end
inside_single_line_block = false
current_block = nil
end
end

@parsed = true
@blocks
end
Expand Down Expand Up @@ -161,4 +171,4 @@ def normalize(text_block)
end

end
end
end
35 changes: 23 additions & 12 deletions lib/kss/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,40 @@ module Kss
# Public: The main KSS parser. Takes a directory full of SASS / SCSS / CSS
# files and parses the KSS within them.
class Parser

# Public: Returns a hash of Sections.
attr_accessor :sections
# Public: Initializes a new parser based on a directory of files. Scans
# within the directory recursively for any comment blocks that look like
# KSS.

# Public: Initializes a new parser based on a directory of files or kss strings.
# Scans within the directory recursively or the strings for any comment blocks
# that look like KSS.
#
# paths - Each path String where style files are located.
def initialize(*paths)
# paths_or_strings - Each path String where style files are located, or each String containing KSS.
def initialize(*paths_or_strings)
@sections = {}

paths.each do |path|
Dir["#{path}/**/*.{css,less,sass,scss}"].each do |filename|
parser = CommentParser.new(filename)
paths_or_strings.each do |path_or_string|
if Dir.exists?(path_or_string)
# argument is a path
path = path_or_string
Dir["#{path}/**/*.{css,less,sass,scss}"].each do |filename|
parser = CommentParser.new(filename)
parser.blocks.each do |comment_block|
add_section comment_block, filename if self.class.kss_block?(comment_block)
end
end
else
# argument is a KSS string
kss_string = path_or_string
parser = CommentParser.new(kss_string)
parser.blocks.each do |comment_block|
add_section comment_block, filename if self.class.kss_block?(comment_block)
add_section comment_block if self.class.kss_block?(comment_block)
end
end
end
end

def add_section comment_text, filename
def add_section comment_text, filename = ''
base_name = File.basename(filename)
section = Section.new(comment_text, base_name)
@sections[section.section] = section
Expand Down
19 changes: 19 additions & 0 deletions test/parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,23 @@ def setup
assert_equal 6, @multiple_parsed.sections.count
end

test "parse from string" do
scss_input =<<-'EOS'
// Your standard form element.
//
// Styleguide 3.0.0
form {
// Your standard text input box.
//
// Styleguide 3.0.1
input[type="text"] {
border: 1px solid #ccc;
}
}
EOS
assert_equal "Your standard form element.", Kss::Parser.new(scss_input).section('3.0.0').description
assert_equal "Your standard text input box.", @sass_parsed.section('3.0.1').description
end

end

0 comments on commit 73cdd12

Please sign in to comment.