css_doc 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cssdoc +43 -0
- data/src/css_doc.rb +16 -0
- data/src/css_doc/css_writer.rb +20 -0
- data/src/css_doc/document.rb +31 -0
- data/src/css_doc/document_collection.rb +33 -0
- data/src/css_doc/document_documentation.rb +5 -0
- data/src/css_doc/document_handler.rb +36 -0
- data/src/css_doc/documentation.rb +111 -0
- data/src/css_doc/driver.rb +85 -0
- data/src/css_doc/examples.rb +12 -0
- data/src/css_doc/rule_set.rb +14 -0
- data/src/css_doc/rule_set_documentation.rb +5 -0
- data/src/css_doc/section.rb +17 -0
- data/src/css_doc/section_documentation.rb +5 -0
- data/src/css_doc/template.rb +47 -0
- data/src/css_pool/visitors/to_css.rb +9 -0
- data/src/rake/css_doc_task.rb +29 -0
- data/src/templates/default/css_doc.css +286 -0
- data/src/templates/default/document.html.erb +93 -0
- data/src/templates/default/example_index.html.erb +9 -0
- data/src/templates/default/file_index.html.erb +7 -0
- data/src/templates/default/index.html.erb +3 -0
- data/src/templates/default/layout.html.erb +30 -0
- data/src/templates/default/section_index.html.erb +14 -0
- data/src/templates/default/selector_index.html.erb +14 -0
- data/src/templates/simple/css_doc.css +282 -0
- data/src/templates/simple/document.html.erb +66 -0
- data/src/templates/simple/file_index.html.erb +7 -0
- data/src/templates/simple/index.html.erb +3 -0
- data/src/templates/simple/layout.html.erb +30 -0
- data/src/templates/simple/section_index.html.erb +14 -0
- data/src/templates/simple/selector_index.html.erb +14 -0
- metadata +98 -0
data/bin/cssdoc
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'css_doc'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
class CSSDocCli
|
7
|
+
def self.run(args)
|
8
|
+
options = {
|
9
|
+
:input_dir => '.',
|
10
|
+
:skip_files => [],
|
11
|
+
:output_dir => 'doc',
|
12
|
+
:template_path => File.expand_path(File.dirname(__FILE__) + "/../src/templates/default")
|
13
|
+
}
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.banner = "Usage: cssdoc [options] [input-dir/input-files]"
|
16
|
+
opts.on("-o", "--output=dir", "Specify output directory") do |dir|
|
17
|
+
options[:output_dir] = dir
|
18
|
+
end
|
19
|
+
opts.on("-s", "--skip=files", "Skip specified files") do |files|
|
20
|
+
options[:skip_files] = files.split(',').collect { |file| file.strip }
|
21
|
+
end
|
22
|
+
opts.on("-p", "--project-name=name", "Specify Project name") do |name|
|
23
|
+
options[:project_name] = name
|
24
|
+
end
|
25
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
26
|
+
options[:verbose] = v
|
27
|
+
end
|
28
|
+
opts.on("-t", "--template=name/path", "Specify template or template path") do |name|
|
29
|
+
if File.directory?(name)
|
30
|
+
options[:template_path] = name
|
31
|
+
else
|
32
|
+
options[:template_path] = File.expand_path(File.dirname(__FILE__) + "/../src/templates/#{name}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end.parse!
|
36
|
+
options[:input_dir] = ARGV.first if ARGV.first
|
37
|
+
|
38
|
+
driver = CSSDoc::Driver.new
|
39
|
+
driver.run(options)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
CSSDocCli.run(ARGV)
|
data/src/css_doc.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'csspool'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/css_doc/document'
|
4
|
+
require File.dirname(__FILE__) + '/css_doc/document_handler'
|
5
|
+
require File.dirname(__FILE__) + '/css_doc/document_collection'
|
6
|
+
require File.dirname(__FILE__) + '/css_doc/section'
|
7
|
+
require File.dirname(__FILE__) + '/css_doc/rule_set'
|
8
|
+
require File.dirname(__FILE__) + '/css_doc/template'
|
9
|
+
require File.dirname(__FILE__) + '/css_doc/documentation'
|
10
|
+
require File.dirname(__FILE__) + '/css_doc/document_documentation'
|
11
|
+
require File.dirname(__FILE__) + '/css_doc/rule_set_documentation'
|
12
|
+
require File.dirname(__FILE__) + '/css_doc/section_documentation'
|
13
|
+
require File.dirname(__FILE__) + '/css_doc/css_writer'
|
14
|
+
require File.dirname(__FILE__) + '/css_doc/driver'
|
15
|
+
require File.dirname(__FILE__) + '/css_doc/examples'
|
16
|
+
require File.dirname(__FILE__) + '/css_pool/visitors/to_css'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CSSDoc
|
2
|
+
class CSSWriter
|
3
|
+
def initialize(collection)
|
4
|
+
@collection = collection
|
5
|
+
end
|
6
|
+
|
7
|
+
def write
|
8
|
+
output = ""
|
9
|
+
@collection.rule_sets.each do |rule_set|
|
10
|
+
selectors = rule_set.selectors.collect { |selector| 'div.example ' + selector.to_css }
|
11
|
+
output << selectors.join(', ')
|
12
|
+
output << '{'
|
13
|
+
output << rule_set.declaration_css
|
14
|
+
output << '}'
|
15
|
+
output << "\n"
|
16
|
+
end
|
17
|
+
output
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module CSSDoc
|
2
|
+
class Document < CSSPool::CSS::Document
|
3
|
+
attr_accessor :documentation
|
4
|
+
attr_accessor :sections
|
5
|
+
attr_accessor :name
|
6
|
+
|
7
|
+
def self.parse string, name
|
8
|
+
unless string && string.length > 0
|
9
|
+
return CSSDoc::Document.new(name)
|
10
|
+
end
|
11
|
+
handler = CSSDoc::DocumentHandler.new(name)
|
12
|
+
parser = CSSPool::SAC::Parser.new(handler)
|
13
|
+
parser.parse(string)
|
14
|
+
handler.document
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(name)
|
18
|
+
super()
|
19
|
+
@name = name
|
20
|
+
@sections = [Section.new(self, '')]
|
21
|
+
end
|
22
|
+
|
23
|
+
def output_file_name
|
24
|
+
name.gsub('.css', '_css.html')
|
25
|
+
end
|
26
|
+
|
27
|
+
def named_sections
|
28
|
+
sections.reject {|section| section.name.nil?}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module CSSDoc
|
2
|
+
class DocumentCollection < CSSPool::CSS::Document
|
3
|
+
attr_accessor :documents
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@documents = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def rule_sets
|
10
|
+
documents.collect { |document| document.rule_sets }.flatten
|
11
|
+
end
|
12
|
+
|
13
|
+
def selectors
|
14
|
+
rule_sets.collect { |rule_set| rule_set.selectors }.flatten
|
15
|
+
end
|
16
|
+
|
17
|
+
def sections
|
18
|
+
documents.collect { |document| document.sections }.flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def named_sections
|
22
|
+
sections.reject { |section| section.name.nil? }
|
23
|
+
end
|
24
|
+
|
25
|
+
def selector_hash
|
26
|
+
selectors.inject({}) { |hash, selector| (hash[selector.to_css] ||= []) << selector; hash }
|
27
|
+
end
|
28
|
+
|
29
|
+
def section_hash
|
30
|
+
named_sections.inject({}) { |hash, section| (hash[section.name] ||= []) << section; hash }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module CSSDoc
|
2
|
+
class DocumentHandler < CSSPool::CSS::DocumentHandler
|
3
|
+
def initialize(name)
|
4
|
+
super()
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
def start_document
|
9
|
+
@document = CSSDoc::Document.new(@name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def comment(comment)
|
13
|
+
if comment =~ /@file/
|
14
|
+
@document.documentation = DocumentDocumentation.new(comment)
|
15
|
+
elsif comment =~ /@section/
|
16
|
+
@document.sections << Section.new(@document, comment)
|
17
|
+
else
|
18
|
+
@last_comment = comment
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_selector(selector_list)
|
23
|
+
rule_set = CSSDoc::RuleSet.new(
|
24
|
+
selector_list,
|
25
|
+
[],
|
26
|
+
@media_stack.last || []
|
27
|
+
)
|
28
|
+
rule_set.document = @document
|
29
|
+
rule_set.documentation = RuleSetDocumentation.new(@last_comment =~ /^\*/ ? @last_comment : "")
|
30
|
+
@last_comment = nil
|
31
|
+
|
32
|
+
@document.rule_sets << rule_set
|
33
|
+
@document.sections.last.rule_sets << rule_set
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module CSSDoc
|
2
|
+
class Documentation
|
3
|
+
class Section
|
4
|
+
attr_accessor :lines
|
5
|
+
def initialize(lines)
|
6
|
+
self.lines = lines
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
lines.join("\n")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class TextSection < Section
|
15
|
+
def to_html
|
16
|
+
result = "<p>"
|
17
|
+
result << lines.collect {|l|l.strip}.join("\n").gsub(/\n\n+/, '</p><p>').gsub(/\n/, ' ').strip
|
18
|
+
result << "</p>"
|
19
|
+
result.gsub('<p></p>', '')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class CodeSection < Section
|
24
|
+
def to_html
|
25
|
+
result = "<pre>" + lines.join("\n").gsub("<", "<").gsub(">", ">").gsub('"', '"') + "</pre>"
|
26
|
+
result << %{<div class="example">#{lines.join("\n")}</div>}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Sections < Array
|
31
|
+
def to_html
|
32
|
+
collect {|section| section.to_html}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :comment
|
37
|
+
attr_accessor :sections
|
38
|
+
|
39
|
+
def self.tags
|
40
|
+
@tags ||= []
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.define_tag(*names)
|
44
|
+
names.each do |name|
|
45
|
+
attr_accessor name
|
46
|
+
tags << name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(comment)
|
51
|
+
@comment = comment
|
52
|
+
@sections = Sections.new
|
53
|
+
parse_documentation
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
@comment
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_tags(line)
|
61
|
+
self.class.tags.each do |tag|
|
62
|
+
rx = /@#{tag.to_s.gsub('_', '-')}/
|
63
|
+
if line =~ rx
|
64
|
+
instance_variable_set(:"@#{tag}", line.gsub(rx, "").strip)
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_comment
|
72
|
+
@parsed_comment ||= comment.gsub(/\*\/$/, '').split("\n").collect { |line| line.gsub(/^\s*\*/, '') }
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_documentation
|
76
|
+
lines = parse_comment
|
77
|
+
parse(lines)
|
78
|
+
end
|
79
|
+
|
80
|
+
def empty?
|
81
|
+
parse_comment.join("\n").strip.empty?
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse(lines)
|
85
|
+
section_type = TextSection
|
86
|
+
section_text = []
|
87
|
+
lines.each do |line|
|
88
|
+
unless parse_tags(line)
|
89
|
+
if line =~ /@code/
|
90
|
+
sections << section_type.new(section_text)
|
91
|
+
section_text = []
|
92
|
+
section_type = CodeSection
|
93
|
+
elsif line =~ /@endcode/
|
94
|
+
sections << section_type.new(section_text)
|
95
|
+
section_text = []
|
96
|
+
section_type = TextSection
|
97
|
+
elsif line =~ /@description/
|
98
|
+
section_text << line.gsub(/@description/, '')
|
99
|
+
else
|
100
|
+
section_text << line
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
sections << section_type.new(section_text)
|
105
|
+
|
106
|
+
sections.each do |section|
|
107
|
+
Examples.add(section) if section.is_a?(CodeSection)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module CSSDoc
|
4
|
+
class Driver
|
5
|
+
def run(options = {})
|
6
|
+
@options = options
|
7
|
+
|
8
|
+
@collection = CSSDoc::DocumentCollection.new
|
9
|
+
|
10
|
+
generate_file_documentation
|
11
|
+
generate_index_documentation
|
12
|
+
generate_css
|
13
|
+
copy_additional_files
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_file_documentation
|
17
|
+
skip_files = @options[:skip_files] || []
|
18
|
+
|
19
|
+
Dir.glob("#{@options[:input_dir]}/**/*.css").each do |file_name|
|
20
|
+
relative_path = file_name.gsub("#{@options[:input_dir]}/", '')
|
21
|
+
next if skip_files.include?(relative_path)
|
22
|
+
|
23
|
+
log "Generating documentation for file #{relative_path} ..."
|
24
|
+
|
25
|
+
FileUtils.mkdir_p("#{@options[:output_dir]}/#{File.dirname(relative_path)}")
|
26
|
+
doc = CSSDoc::Document.parse(File.read(file_name), relative_path)
|
27
|
+
|
28
|
+
generate(:template => 'document', :file_name => doc.output_file_name, :locals => { :document => doc, :title => doc.name })
|
29
|
+
|
30
|
+
@collection.documents << doc
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def generate_index_documentation
|
35
|
+
log "Generating Selector Index ..."
|
36
|
+
|
37
|
+
generate(:template => 'selector_index', :locals => { :collection => @collection, :title => 'Selector Index' })
|
38
|
+
|
39
|
+
log "Generating File Index ..."
|
40
|
+
|
41
|
+
generate(:template => 'file_index', :locals => { :collection => @collection, :title => 'File Index' })
|
42
|
+
|
43
|
+
log "Generating Section Index ..."
|
44
|
+
|
45
|
+
generate(:template => 'section_index', :locals => { :collection => @collection, :title => 'Section Index' })
|
46
|
+
|
47
|
+
log "Generating Example Index ..."
|
48
|
+
|
49
|
+
generate(:template => 'example_index', :locals => { :collection => @collection, :title => 'Example Index' })
|
50
|
+
|
51
|
+
log "Generating Index Page ..."
|
52
|
+
|
53
|
+
generate(:template => 'index', :locals => { :project_name => @options[:project_name], :title => 'Index' })
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_css
|
57
|
+
log "Generating Example CSS ..."
|
58
|
+
|
59
|
+
writer = CSSDoc::CSSWriter.new(@collection)
|
60
|
+
File.open("#{@options[:output_dir]}/styles.css", 'w') { |file| file.puts writer.write }
|
61
|
+
end
|
62
|
+
|
63
|
+
def copy_additional_files
|
64
|
+
log "Copying Additional Files ..."
|
65
|
+
|
66
|
+
FileUtils.cp("#{@options[:template_path]}/css_doc.css", "#{@options[:output_dir]}/")
|
67
|
+
end
|
68
|
+
|
69
|
+
def log(string)
|
70
|
+
puts string if @options[:verbose]
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def generate(params)
|
75
|
+
file_name = params[:file_name] || params[:template]
|
76
|
+
file_name += '.html' unless file_name =~ /\.html$/
|
77
|
+
|
78
|
+
relative_root = '.'
|
79
|
+
relative_root = (['..'] * File.dirname(file_name).split('/').size).join('/') if file_name =~ /\//
|
80
|
+
|
81
|
+
html = CSSDoc::Template.new(@options.merge(:relative_root => relative_root)).render(params[:template], params[:locals])
|
82
|
+
File.open("#{@options[:output_dir]}/#{file_name}", 'w') { |file| file.puts html }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module CSSDoc
|
2
|
+
class RuleSet < CSSPool::CSS::RuleSet
|
3
|
+
attr_accessor :document
|
4
|
+
attr_accessor :documentation
|
5
|
+
|
6
|
+
def selector_css
|
7
|
+
@selector_css ||= selectors.collect { |selector| selector.to_css }.join(", ")
|
8
|
+
end
|
9
|
+
|
10
|
+
def declaration_css
|
11
|
+
@declaration_css ||= declarations.collect { |declaration| declaration.to_css }.join(' ')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module CSSDoc
|
2
|
+
class Section
|
3
|
+
attr_accessor :document
|
4
|
+
attr_accessor :rule_sets
|
5
|
+
attr_accessor :documentation
|
6
|
+
|
7
|
+
def initialize(document, comment)
|
8
|
+
@document = document
|
9
|
+
@rule_sets = []
|
10
|
+
@documentation = SectionDocumentation.new(comment)
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
documentation.section
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|