diff --git a/jekyll.gemspec b/jekyll.gemspec index a891f0bb..f5011ba9 100644 --- a/jekyll.gemspec +++ b/jekyll.gemspec @@ -34,6 +34,7 @@ Gem::Specification.new do |s| s.add_runtime_dependency('colorator', "~> 0.1") s.add_runtime_dependency('redcarpet', "~> 3.0") s.add_runtime_dependency('toml', '~> 0.1.0') + s.add_runtime_dependency('sass', '~> 3.2') s.add_development_dependency('rake', "~> 10.1") s.add_development_dependency('rdoc', "~> 3.11") diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 4b45e2ba..02509040 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -27,6 +27,7 @@ require 'liquid' require 'maruku' require 'colorator' require 'toml' +require 'sass' # internal requires require 'jekyll/core_ext' diff --git a/lib/jekyll/converters/sass.rb b/lib/jekyll/converters/sass.rb new file mode 100644 index 00000000..0c36eb65 --- /dev/null +++ b/lib/jekyll/converters/sass.rb @@ -0,0 +1,58 @@ +module Jekyll + class Sass < Converter + safe true + priority :low + + def matches(ext) + ext =~ /^\.s(a|c)ss$/i + end + + def output_ext(ext) + ".css" + end + + def jekyll_sass_configuration + @config["sass"] || {} + end + + def sass_build_configuration_options(overrides) + jekyll_sass_configuration.deep_merge(overrides).symbolize_keys + end + + def syntax_type_of_content(content) + if content.include?(";") || content.include?("{") + :scss + else + :sass + end + end + + def sass_dir + return "_sass" if jekyll_sass_configuration["sass_dir"].to_s.empty? + jekyll_sass_configuration["sass_dir"] + end + + def sass_dir_relative_to_site_source + File.join( + @config["source"], + File.expand_path(sass_dir, "/") # FIXME: Not windows-compatible + ) + end + + def allow_caching? + !@config["safe"] + end + + def sass_configs(content = "") + sass_build_configuration_options({ + "syntax" => syntax_type_of_content(content), + "cache" => allow_caching?, + "load_paths" => [sass_dir_relative_to_site_source] + }) + end + + def convert(content) + ::Sass.compile(content, sass_configs(content)) + end + end +end diff --git a/site/_data/docs.yml b/site/_data/docs.yml index 4e89bcb2..1c790636 100644 --- a/site/_data/docs.yml +++ b/site/_data/docs.yml @@ -15,6 +15,7 @@ - pages - variables - datafiles + - assets - migrations - title: Customization diff --git a/site/docs/assets.md b/site/docs/assets.md new file mode 100644 index 00000000..5191dc15 --- /dev/null +++ b/site/docs/assets.md @@ -0,0 +1,46 @@ +--- +layout: docs +title: Assets +prev_section: datafiles +next_section: migrations +permalink: /docs/assets/ +--- + +Jekyll provides built-in support for Sass and CoffeeScript. In order to use +them, create a file with the proper extension name (one of `.sass`, `.scss`, +or `.coffee`) and start the file with two lines of triple dashes, like this: + +{% highlight sass %} +--- +--- + +// start content +.my-definition + font-size: 1.2em +{% endhighlight %} + +## Sass/SCSS + +Jekyll allows you to customize your Sass conversion in certain ways. + +If you are using Sass `@import` statements, you'll need to ensure that your +`sass_dir` is set to the base directory that contains your Sass files. You +can do that thusly: + +{% highlight yaml %} +sass: + sass_dir: _sass +{% endhighlight %} + +The Sass converter will default to `_sass`. + +You may also specify the output style with the `style` option in your +`_config.yml` file: + +{% highlight yaml %} +sass: + style: :compressed +{% endhighlight %} + +These are passed to Sass, so any output style options Sass supports are valid +here, too. diff --git a/site/docs/datafiles.md b/site/docs/datafiles.md index b3421c38..55af6ec4 100644 --- a/site/docs/datafiles.md +++ b/site/docs/datafiles.md @@ -2,25 +2,25 @@ layout: docs title: Data Files prev_section: variables -next_section: migrations +next_section: assets permalink: /docs/datafiles/ --- In addition to the [built-in variables](../variables/) available from Jekyll, -you can specify your own custom data that can be accessed via the [Liquid +you can specify your own custom data that can be accessed via the [Liquid templating system](http://wiki.github.com/shopify/liquid/liquid-for-designers). -Jekyll supports loading data from [YAML](http://yaml.org/) files located in the +Jekyll supports loading data from [YAML](http://yaml.org/) files located in the `_data` directory. This powerful feature allows you to avoid repetition in your templates and to -set site specific options without changing `_config.yml`. +set site specific options without changing `_config.yml`. Plugins/themes can also leverage Data Files to set configuration variables. ## The Data Folder -As explained on the [directory structure](../structure/) page, the `_data` +As explained on the [directory structure](../structure/) page, the `_data` folder is where you can store additional data for Jekyll to use when generating your site. These files must be YAML files (using either the `.yml` or `.yaml` extension) and they will be accessible via `site.data`. diff --git a/site/docs/migrations.md b/site/docs/migrations.md index 27ecf71d..f9ecc1f5 100644 --- a/site/docs/migrations.md +++ b/site/docs/migrations.md @@ -1,7 +1,7 @@ --- layout: docs title: Blog migrations -prev_section: datafiles +prev_section: assets next_section: templates permalink: /docs/migrations/ --- diff --git a/test/test_sass.rb b/test/test_sass.rb new file mode 100644 index 00000000..d13fbcfe --- /dev/null +++ b/test/test_sass.rb @@ -0,0 +1,107 @@ +require 'helper' + +class TestSass < Test::Unit::TestCase + def site_configuration(overrides = {}) + Jekyll::Configuration::DEFAULTS.deep_merge(overrides).deep_merge({ + "source" => source_dir, + "destination" => dest_dir + }) + end + + def converter(overrides = {}) + Jekyll::Sass.new(site_configuration({"sass" => overrides})) + end + + def sass_content + <<-SASS +$font-stack: Helvetica, sans-serif +body + font-family: $font-stack + font-color: fuschia +SASS + end + + def scss_content + <<-SCSS +$font-stack: Helvetica, sans-serif; +body { + font-family: $font-stack; + font-color: fuschia; +} +SCSS + end + + def css_output + <<-CSS +body {\n font-family: Helvetica, sans-serif;\n font-color: fuschia; } +CSS + end + + context "matching file extensions" do + should "match .scss files" do + assert converter.matches(".scss") + end + + should "match .sass files" do + assert converter.matches(".sass") + end + end + + context "determining the output file extension" do + should "always outputs the .css file extension" do + assert_equal ".css", converter.output_ext(".always-css") + end + end + + context "when building configurations" do + should "not allow caching in safe mode" do + verter = converter + verter.instance_variable_get(:@config)["safe"] = true + assert_equal false, verter.sass_configs[:cache] + end + + should "allow caching in unsafe mode" do + assert_equal true, converter.sass_configs[:cache] + end + + should "set the load paths to the _sass dir relative to site source" do + assert_equal [source_dir("_sass")], converter.sass_configs[:load_paths] + end + + should "allow the user to specify a different sass dir" do + assert_equal [source_dir("_scss")], converter({"sass_dir" => "_scss"}).sass_configs[:load_paths] + end + + should "set syntax :scss when SCSS content" do + assert_equal :scss, converter.sass_configs(scss_content)[:syntax] + end + + should "set syntax :sass when Sass content" do + assert_equal :sass, converter.sass_configs(sass_content)[:syntax] + end + + should "default to :sass syntax when content is empty" do + assert_equal :sass, converter.sass_configs[:syntax] + end + + should "not allow sass_dirs outside of site source" do + assert_equal source_dir("etc/passwd"), converter({"sass_dir" => "/etc/passwd"}).sass_dir_relative_to_site_source + end + + should "override user-set syntax based on content" do + assert_equal :sass, converter({"syntax" => :scss}).sass_configs(sass_content)[:syntax] + end + end + + context "converting sass" do + should "produce CSS" do + assert_equal css_output, converter.convert(sass_content) + end + end + + context "converting SCSS" do + should "produce CSS" do + assert_equal css_output, converter.convert(scss_content) + end + end +end