css_doc 0.0.6
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.
- 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
|