2010-01-23 02:16:25 +00:00
|
|
|
require 'rdiscount'
|
2010-01-21 19:54:47 +00:00
|
|
|
|
|
|
|
def stylesheets_dir(framework)
|
|
|
|
Compass::Frameworks[framework].stylesheets_directory
|
|
|
|
end
|
|
|
|
|
2010-02-07 17:14:20 +00:00
|
|
|
def tree_key(item)
|
|
|
|
"tree/"+[item[:framework], item[:stylesheet]].join("/")
|
2010-01-21 19:54:47 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def tree(item)
|
2010-02-07 17:14:20 +00:00
|
|
|
@site.cached(tree_key(item)) do
|
2010-01-21 19:54:47 +00:00
|
|
|
file = File.join(stylesheets_dir(item[:framework]), item[:stylesheet])
|
|
|
|
contents = File.read(file)
|
2010-04-12 09:46:33 +00:00
|
|
|
syntax = item[:stylesheet] =~ /\.scss$/ ? :scss : :sass
|
|
|
|
Sass::Engine.new(contents, :syntax => syntax).send :to_tree
|
2010-01-21 19:54:47 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def imports(item)
|
|
|
|
sass_tree = tree(item)
|
|
|
|
imports = []
|
|
|
|
sass_tree.children.each do |child|
|
|
|
|
if child.is_a?(Sass::Tree::ImportNode)
|
|
|
|
imports << child.imported_filename
|
|
|
|
end
|
|
|
|
end
|
2010-04-26 02:02:18 +00:00
|
|
|
imports.sort
|
2010-01-21 19:54:47 +00:00
|
|
|
end
|
2010-01-22 19:40:56 +00:00
|
|
|
|
2010-02-03 16:02:27 +00:00
|
|
|
def reference_item(options)
|
2010-01-24 07:01:30 +00:00
|
|
|
stylesheet = options[:stylesheet]
|
2010-07-09 05:19:11 +00:00
|
|
|
path = stylesheet_path(stylesheet)
|
|
|
|
if path
|
|
|
|
@site.cached("reference/item/#{path}") do
|
2010-02-07 17:14:20 +00:00
|
|
|
@items.detect do |i|
|
2010-04-24 23:34:04 +00:00
|
|
|
if i.identifier =~ /^\/reference/ && i[:stylesheet]
|
|
|
|
i[:stylesheet] == path
|
|
|
|
end
|
2010-02-07 17:14:20 +00:00
|
|
|
end
|
2010-01-24 07:01:30 +00:00
|
|
|
end
|
2010-02-03 16:02:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-03-28 06:23:45 +00:00
|
|
|
def departialize(path)
|
|
|
|
path.gsub(%r{(\b|/)_}){|m| m.size > 1 ? "/" : ""}
|
|
|
|
end
|
|
|
|
|
2010-02-03 16:02:27 +00:00
|
|
|
def reference_path(options)
|
|
|
|
if item = reference_item(options)
|
|
|
|
rep = item.reps.find { |r| r.name == :default }
|
|
|
|
rep.path
|
2010-01-24 07:01:30 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def import_paths
|
2010-07-09 05:19:11 +00:00
|
|
|
paths = []
|
2010-01-28 08:37:17 +00:00
|
|
|
if @item[:stylesheet]
|
|
|
|
paths << [File.join(Compass::Frameworks[@item[:framework]].stylesheets_directory,
|
2010-07-09 05:19:11 +00:00
|
|
|
File.dirname(@item[:stylesheet])),
|
|
|
|
@item[:stylesheet]["/"] ? File.dirname(@item[:stylesheet]) : ""]
|
2010-01-28 08:37:17 +00:00
|
|
|
end
|
2011-12-28 08:57:00 +00:00
|
|
|
|
2010-07-09 05:19:11 +00:00
|
|
|
paths += Compass::Frameworks::ALL.inject([]) {|m, f| m << f.stylesheets_directory}.map!{|p|[p, '']}
|
2010-01-28 08:37:17 +00:00
|
|
|
paths
|
2010-01-24 07:01:30 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def stylesheet_path(ss)
|
2010-07-09 05:19:11 +00:00
|
|
|
possible_names = possible_filenames_for_stylesheet(ss)
|
|
|
|
import_paths.each do |import_path|
|
|
|
|
possible_names.each do |filename|
|
|
|
|
full_path = File.join(import_path.first, filename)
|
|
|
|
if File.exist?(full_path)
|
|
|
|
return "#{import_path.last}#{"/" if import_path.last && import_path.last.length > 0}#{filename}"
|
2010-01-24 07:01:30 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2010-07-09 05:19:11 +00:00
|
|
|
nil
|
2010-01-24 07:01:30 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def possible_filenames_for_stylesheet(ss)
|
|
|
|
ext = File.extname(ss)
|
|
|
|
path = File.dirname(ss)
|
2010-01-25 00:02:53 +00:00
|
|
|
path = path == "." ? "" : "#{path}/"
|
2010-01-24 07:01:30 +00:00
|
|
|
base = File.basename(ss)[0..-(ext.size+1)]
|
|
|
|
extensions = if ext.size > 0
|
|
|
|
[ext]
|
|
|
|
else
|
2010-07-09 05:19:11 +00:00
|
|
|
[".scss", ".sass"]
|
2010-01-24 07:01:30 +00:00
|
|
|
end
|
2010-07-09 05:19:11 +00:00
|
|
|
basenames = ["_#{base}", base]
|
2010-01-24 07:01:30 +00:00
|
|
|
filenames = []
|
|
|
|
basenames.each do |basename|
|
|
|
|
extensions.each do |extension|
|
2010-01-25 00:02:53 +00:00
|
|
|
filenames << "#{path}#{basename}#{extension}"
|
2010-01-24 07:01:30 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
filenames
|
|
|
|
end
|
|
|
|
|
2010-01-22 19:40:56 +00:00
|
|
|
def mixins(item)
|
|
|
|
sass_tree = tree(item)
|
|
|
|
mixins = []
|
|
|
|
comment = nil
|
|
|
|
sass_tree.children.each do |child|
|
|
|
|
if child.is_a?(Sass::Tree::MixinDefNode)
|
2010-03-16 23:39:56 +00:00
|
|
|
child.comment = comment && Sass::Tree::CommentNode.clean(comment)
|
2010-01-22 19:40:56 +00:00
|
|
|
comment = nil
|
|
|
|
mixins << child
|
|
|
|
elsif child.is_a?(Sass::Tree::CommentNode)
|
|
|
|
comment ||= ""
|
|
|
|
comment << "\n" unless comment.empty?
|
|
|
|
comment << child.docstring
|
|
|
|
else
|
|
|
|
comment = nil
|
|
|
|
end
|
|
|
|
end
|
2010-05-01 22:20:16 +00:00
|
|
|
mixins.reject{|m| m.comment =~ /@private/}
|
2010-01-22 19:40:56 +00:00
|
|
|
end
|
|
|
|
|
2012-03-13 16:21:05 +00:00
|
|
|
def selectors(item)
|
|
|
|
sass_tree = tree(item)
|
|
|
|
# Visitors::CheckNesting.visit(sass_tree)
|
|
|
|
# sass_tree = Visitors::Perform.visit(sass_tree)
|
|
|
|
selectors = []
|
|
|
|
comment = nil
|
|
|
|
sass_tree.children.each do |child|
|
|
|
|
case child
|
|
|
|
when Sass::Tree::RuleNode
|
|
|
|
child.comment = comment && Sass::Tree::CommentNode.clean(comment)
|
|
|
|
comment = nil
|
|
|
|
selectors << child
|
|
|
|
when Sass::Tree::CommentNode
|
|
|
|
comment ||= ""
|
|
|
|
comment << "\n" unless comment.empty?
|
|
|
|
comment << child.docstring
|
|
|
|
else
|
|
|
|
comment = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
selectors.reject!{|s| s.comment =~ /@private/}
|
|
|
|
# selectors.select!{|s| s.comment.strip.size > 0} # this would cause only documented selectors to be output
|
|
|
|
selectors
|
|
|
|
end
|
|
|
|
|
2011-01-02 20:34:16 +00:00
|
|
|
def functions(item)
|
|
|
|
sass_tree = tree(item)
|
|
|
|
functions = []
|
|
|
|
comment = nil
|
|
|
|
sass_tree.children.each do |child|
|
|
|
|
if child.is_a?(Sass::Tree::FunctionNode)
|
|
|
|
child.comment = comment && Sass::Tree::CommentNode.clean(comment)
|
|
|
|
comment = nil
|
|
|
|
functions << child
|
|
|
|
elsif child.is_a?(Sass::Tree::CommentNode)
|
|
|
|
comment ||= ""
|
|
|
|
comment << "\n" unless comment.empty?
|
|
|
|
comment << child.docstring
|
|
|
|
else
|
|
|
|
comment = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
functions.reject{|m| m.comment =~ /@private/}
|
|
|
|
end
|
|
|
|
|
2010-01-24 03:47:28 +00:00
|
|
|
def constants(item)
|
|
|
|
sass_tree = tree(item)
|
|
|
|
constants = []
|
|
|
|
comment = nil
|
|
|
|
sass_tree.children.each do |child|
|
|
|
|
if child.is_a?(Sass::Tree::VariableNode)
|
2010-03-29 06:09:03 +00:00
|
|
|
child.comment = comment && Sass::Tree::CommentNode.clean(comment)
|
2010-01-24 03:47:28 +00:00
|
|
|
comment = nil
|
2010-07-10 20:44:17 +00:00
|
|
|
child.name.tr!("_",'-')
|
2010-01-24 03:47:28 +00:00
|
|
|
constants << child
|
|
|
|
elsif child.is_a?(Sass::Tree::CommentNode)
|
|
|
|
comment ||= ""
|
|
|
|
comment << "\n" unless comment.empty?
|
|
|
|
comment << child.docstring
|
|
|
|
else
|
|
|
|
comment = nil
|
|
|
|
end
|
|
|
|
end
|
2010-10-11 11:24:03 +00:00
|
|
|
constants.reject{|c| c.comment =~ /@private/}
|
2010-01-24 03:47:28 +00:00
|
|
|
end
|
|
|
|
|
2010-08-01 16:52:17 +00:00
|
|
|
def all_constants
|
2011-01-04 18:42:05 +00:00
|
|
|
@items.inject([]) do |variables, item|
|
|
|
|
next variables unless item.identifier =~ %r{/reference}
|
|
|
|
next variables unless item[:stylesheet]
|
|
|
|
variables += constants(item).map{|v| [item, v] }
|
2010-08-01 16:52:17 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def all_mixins
|
2011-01-04 18:42:05 +00:00
|
|
|
@items.inject([]) do |all_mixins, item|
|
|
|
|
next all_mixins unless item.identifier =~ %r{/reference}
|
|
|
|
next all_mixins unless item[:stylesheet]
|
|
|
|
all_mixins += mixins(item).map{|m| [item, m] }
|
2010-08-01 16:52:17 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-01-02 20:34:16 +00:00
|
|
|
def all_functions
|
2011-01-05 17:34:45 +00:00
|
|
|
@items.inject([]) do |all_functions, item|
|
2011-01-04 18:42:05 +00:00
|
|
|
next all_functions unless item.identifier =~ %r{/reference}
|
|
|
|
next all_functions unless item[:stylesheet]
|
|
|
|
all_functions += functions(item).map{|f| [item, f] }
|
2011-01-02 20:34:16 +00:00
|
|
|
end
|
2010-01-22 19:40:56 +00:00
|
|
|
end
|
|
|
|
|
2011-12-28 08:57:00 +00:00
|
|
|
# Sass Only Functions from 3.1.10 (Brainy Betty)
|
|
|
|
# Not as elegant, but does the trick.
|
|
|
|
def sass_functions
|
|
|
|
[:rgb, :rgba, :hsl, :hsla, :red, :green, :blue, :hue, :saturation, :lightness, :alpha, :opacity, :opacify, :fade_in, :transparentize, :fade_out, :lighten, :darken, :saturate, :desaturate, :adjust_hue, :adjust_color, :scale_color, :change_color, :mix, :grayscale, :complement, :invert, :unquote, :quote, :type_of, :unit, :unitless, :comparable, :percentage, :round, :ceil, :floor, :abs, :length, :nth, :join, :append, :zip, :index, :if]
|
|
|
|
end
|
|
|
|
|
2010-01-30 23:50:25 +00:00
|
|
|
def example_items
|
2010-02-07 17:14:20 +00:00
|
|
|
@site.cached("examples") do
|
2010-02-07 17:37:07 +00:00
|
|
|
@items.select do |i|
|
|
|
|
i.identifier =~ /^\/examples/ && i[:example]
|
|
|
|
end
|
2010-02-07 17:14:20 +00:00
|
|
|
end
|
2010-01-30 23:50:25 +00:00
|
|
|
end
|
|
|
|
|
2011-01-05 17:34:45 +00:00
|
|
|
def item_for_function_name(function_name)
|
|
|
|
@items.detect do |item|
|
|
|
|
(item.identifier =~ %r{helpers}) && item[:documented_functions] && item[:documented_functions].include?(function_name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-01-30 23:50:25 +00:00
|
|
|
def examples_for_item(item)
|
2010-02-07 17:14:20 +00:00
|
|
|
@site.cached("examples/#{item.identifier}") do
|
|
|
|
example_items.select do |i|
|
|
|
|
i[:framework] == item[:framework] &&
|
|
|
|
i[:stylesheet] == item[:stylesheet]
|
|
|
|
end
|
2010-01-30 23:50:25 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-01-31 00:20:03 +00:00
|
|
|
def examples(item, mixin = nil)
|
|
|
|
examples = examples_for_item(item)
|
|
|
|
if mixin
|
|
|
|
examples = examples.select {|i| i[:mixin] == mixin.name }
|
|
|
|
else
|
|
|
|
examples = examples.reject {|i| i[:mixin] }
|
|
|
|
end
|
|
|
|
examples.map{|i| i.reps.find{|r| r.name == :default}}
|
2010-01-27 06:08:13 +00:00
|
|
|
end
|
2010-01-24 03:47:28 +00:00
|
|
|
|
2010-01-23 02:16:25 +00:00
|
|
|
def format_doc(docstring)
|
2010-01-25 00:02:53 +00:00
|
|
|
if docstring
|
|
|
|
RDiscount.new(docstring).to_html
|
|
|
|
end
|
2010-01-23 02:16:25 +00:00
|
|
|
end
|
|
|
|
|