├── .gitignore
├── .travis.yml
├── Gemfile
├── History.markdown
├── LICENSE.txt
├── README.md
├── Rakefile
├── jekyll-opal.gemspec
├── lib
├── jekyll-opal.rb
├── jekyll-opal
│ └── version.rb
└── jekyll
│ ├── converters
│ └── opal.rb
│ └── generators
│ └── opal.rb
├── script
├── bootstrap
└── cibuild
└── spec
├── opal_converter_spec.rb
├── opal_generator_spec.rb
└── spec_helper.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | *.rbc
3 | .bundle
4 | .config
5 | .yardoc
6 | Gemfile.lock
7 | InstalledFiles
8 | _yardoc
9 | coverage
10 | doc/
11 | lib/bundler/man
12 | pkg
13 | rdoc
14 | spec/reports
15 | spec/dest
16 | test/tmp
17 | test/version_tmp
18 | tmp
19 | *.bundle
20 | *.so
21 | *.o
22 | *.a
23 | mkmf.log
24 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | cache: bundler
3 | rvm:
4 | - 2.6
5 | - 2.4
6 |
7 | matrix:
8 | include:
9 | -
10 | rvm: 1.9
11 | env: JEKYLL_VERSION=2.0
12 |
13 | script : script/cibuild
14 | branches:
15 | only:
16 | - master
17 |
18 | notifications:
19 | email: false
20 |
21 | env:
22 | - JEKYLL_VERSION=3.0
23 | - JEKYLL_VERSION=2.0
24 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec
3 |
--------------------------------------------------------------------------------
/History.markdown:
--------------------------------------------------------------------------------
1 | ## 0.3.0 / 2016-06-13
2 |
3 | ### Minor Enhancements
4 |
5 | * Allow using versions of Opal beyond 0.8.x (aka 0.9.x) (#10)
6 |
7 | ## 0.2.0 / 2015-11-25
8 |
9 | ### Minor Enhancements
10 |
11 | * Bump Opal dependency to v0.8.x (#8)
12 |
13 | ### Development Fixes
14 |
15 | * Test against Jekyll 2 & 3 (#8)
16 |
17 | ## 0.1.0 / 2014-06-16
18 |
19 | * Birthday!
20 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-present Parker Moore and the jekyll-opal contributors
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Jekyll-Opal
2 |
3 | Let Jekyll convert your Ruby into JavaScript using [Opal](https://github.com/opal/opal).
4 |
5 | [](https://travis-ci.org/jekyll/jekyll-opal)
6 |
7 | ## Installation
8 |
9 | Add this line to your application's Gemfile:
10 |
11 | gem 'jekyll-opal'
12 |
13 | And then execute:
14 |
15 | $ bundle
16 |
17 | Or install it yourself as:
18 |
19 | $ gem install jekyll-opal
20 |
21 | ## Usage
22 |
23 | Write your Opal in `.opal` files (be sure to add the two `---` lines at the
24 | top to make them pages!!)
25 |
26 | This plugin comes with a generator which creates the Opal library file in
27 | the destination, under `js/opal.js`, if it's not already there. To prevent
28 | backwards-incompatible sites, we ship a `{{ site.opal.url }}` variable for
29 | your use in your sites. When output, it will look like this: `/js/opal.js`.
30 |
31 | If your site is served in a subfolder (i.e. `http://example.org/subfolder/`), simply prepend a baseurl:
32 |
33 | ```html
34 |
35 | ```
36 |
37 | You can even prepend variables! Perhaps a URL?
38 |
39 | ```html
40 |
41 | ```
42 |
43 | Feel free to chain them like that -- they're just Liquid filters.
44 |
45 | File an issue if something isn't clear!
46 |
47 | ## Contributing
48 |
49 | 1. Fork it ( https://github.com/jekyll/jekyll-opal/fork )
50 | 2. Create your feature branch (`git checkout -b my-new-feature`)
51 | 3. Commit your changes (`git commit -am 'Add some feature'`)
52 | 4. Push to the branch (`git push origin my-new-feature`)
53 | 5. Create a new Pull Request
54 |
55 | ## License
56 |
57 | MIT. See the [License](LICENSE.txt) file for more details
58 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/gem_tasks"
2 |
3 |
--------------------------------------------------------------------------------
/jekyll-opal.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'jekyll-opal/version'
5 |
6 | Gem::Specification.new do |spec|
7 | spec.name = "jekyll-opal"
8 | spec.version = Jekyll::Opal::VERSION
9 | spec.authors = ["Parker Moore"]
10 | spec.email = ["parkrmoore@gmail.com"]
11 | spec.summary = %q{Let Jekyll convert your Ruby into JavaScript using Opal.}
12 | spec.homepage = "https://github.com/jekyll/jekyll-opal"
13 | spec.license = "MIT"
14 |
15 | spec.files = `git ls-files -z`.split("\x0")
16 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18 | spec.require_paths = ["lib"]
19 |
20 | spec.add_runtime_dependency "opal", "~> 0.8"
21 |
22 | spec.add_development_dependency "bundler"
23 | spec.add_development_dependency "rake"
24 | spec.add_development_dependency "rspec", "~> 3.0"
25 | spec.add_development_dependency "jekyll", ENV["JEKYLL_VERSION"] ? "~> #{ENV["JEKYLL_VERSION"]}" : ">= 2.0"
26 | end
27 |
--------------------------------------------------------------------------------
/lib/jekyll-opal.rb:
--------------------------------------------------------------------------------
1 | require "jekyll-opal/version"
2 | require "jekyll/converters/opal"
3 | require "jekyll/generators/opal"
4 |
5 | module Jekyll
6 | module Opal
7 | OPAL_LIB_LOCATION = File.join("js", "opal.js").freeze
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/lib/jekyll-opal/version.rb:
--------------------------------------------------------------------------------
1 | module Jekyll
2 | module Opal
3 | VERSION = "0.3.0"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/lib/jekyll/converters/opal.rb:
--------------------------------------------------------------------------------
1 | require 'opal'
2 |
3 | module Jekyll
4 | module Converters
5 | class Opal < Converter
6 |
7 | def matches(ext)
8 | !!(ext =~ /\.opal/i)
9 | end
10 |
11 | def output_ext(ext)
12 | ".js"
13 | end
14 |
15 | def convert(content)
16 | ::Opal.compile(content)
17 | end
18 |
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/lib/jekyll/generators/opal.rb:
--------------------------------------------------------------------------------
1 | require 'opal'
2 |
3 | module Jekyll
4 | module Generators
5 | class Opal < Generator
6 |
7 | def generate(site)
8 | write_file(output_location(site)) unless File.file?(output_location(site))
9 | keep_the_file(site)
10 | save_lib_file_location_to_config(site)
11 | end
12 |
13 | def write_file(location)
14 | ensure_directory(location)
15 | File.open(location, 'wb') do |f|
16 | f.puts(opal_stdlib)
17 | end
18 | location
19 | end
20 |
21 | def opal_stdlib
22 | ::Opal::Builder.build('opal')
23 | end
24 |
25 | def ensure_directory(location)
26 | dir = File.dirname(location)
27 | unless File.directory?(dir)
28 | require 'fileutils'
29 | FileUtils.mkdir_p(dir)
30 | end
31 | end
32 |
33 | def output_location(site)
34 | File.expand_path(opal_lib_relative_path, site.dest)
35 | end
36 |
37 | def keep_the_file(site)
38 | (site.keep_files ||= []) << opal_lib_relative_path
39 | end
40 |
41 | def save_lib_file_location_to_config(site)
42 | site.config["opal"] = {
43 | "version" => ::Opal::VERSION,
44 |
45 | # must start with a forward slash!
46 | "url" => File.join("", opal_lib_relative_path)
47 | }
48 | end
49 |
50 | def opal_lib_relative_path
51 | Jekyll::Opal::OPAL_LIB_LOCATION
52 | end
53 |
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/script/bootstrap:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env bash
2 |
3 | bundle install
4 |
--------------------------------------------------------------------------------
/script/cibuild:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | bundle exec rspec --color --require spec_helper
4 |
--------------------------------------------------------------------------------
/spec/opal_converter_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe(Jekyll::Converters::Opal) do
4 | let(:bogus_opal) { "hi.there( oatmeal" }
5 | let(:simple_opal) { "puts 'ohai jekyll'" }
6 | let(:simple_js_output) do
7 | <<-JS
8 | /* Generated by Opal #{::Opal::VERSION} */
9 | (function(Opal) {
10 | Opal.dynamic_require_severity = "error";
11 | var OPAL_CONFIG = { method_missing: true, arity_check: false, freezing: true, tainting: true };
12 | var self = Opal.top, $scope = Opal, nil = Opal.nil, $breaker = Opal.breaker, $slice = Opal.slice;
13 |
14 | Opal.add_stubs(['$puts']);
15 | return self.$puts("ohai jekyll")
16 | })(Opal);
17 | JS
18 | end
19 |
20 | it "matches .opal files" do
21 | expect(subject.matches(".opal")).to be_truthy
22 | end
23 |
24 | it "outputs .js" do
25 | expect(subject.output_ext("ANYTHING AT ALL")).to eql(".js")
26 | end
27 |
28 | it "converts Ruby into Opal" do
29 | expect(subject.convert(simple_opal)).to eql(simple_js_output)
30 | end
31 |
32 | it "explodes on bad input" do
33 | expect(->{ subject.convert(bogus_opal) }).to raise_error(RuntimeError)
34 | end
35 |
36 | end
37 |
--------------------------------------------------------------------------------
/spec/opal_generator_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe(Jekyll::Generators::Opal) do
4 | let(:output_dir) { dest_dir("js") }
5 | let(:output_file) { dest_dir("js", "opal.js") }
6 | let(:site) { fixture_site }
7 |
8 | it "knows where to output the file" do
9 | expect(subject.output_location(site)).to eql(output_file)
10 | end
11 |
12 | it "can build the opal stdlib" do
13 | expect(subject.opal_stdlib.to_s).to match("(Opal);")
14 | end
15 |
16 | context "when ensuring directory is there" do
17 | before(:each) do
18 | FileUtils.rm_r(output_dir) if File.directory?(output_dir)
19 | subject.ensure_directory(subject.output_location(site))
20 | end
21 |
22 | it "creates the proper output directory" do
23 | expect(File.directory?(output_dir)).to be_truthy
24 | end
25 | end
26 |
27 | context "for a fresh site" do
28 | before(:each) do
29 | FileUtils.rm_r(dest_dir) if File.directory?(dest_dir)
30 | end
31 |
32 | it "writes the file" do
33 | expect(subject.write_file(subject.output_location(site))).to eql(output_file)
34 | expect(File.file?(output_file)).to be(true)
35 | end
36 | end
37 |
38 | it "adds the outputted file to the site.keep_files list" do
39 | expect(subject.keep_the_file(site)).to include("js/opal.js")
40 | expect(site.keep_files).to eql(%w(.git .svn js/opal.js))
41 | end
42 |
43 | it "adds the 'opal' namespace for liquid" do
44 | expect(subject.save_lib_file_location_to_config(site)).to eql({
45 | "version" => Opal::VERSION, "url" => "/js/opal.js"
46 | })
47 | expect(site.config.has_key?("opal")).to be_truthy
48 | end
49 |
50 | end
51 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'fileutils'
2 | require 'jekyll'
3 |
4 | TEST_DIR = File.dirname(__FILE__)
5 | PROJECT_DIR = File.dirname(TEST_DIR)
6 | FIXTURE_DIR = File.expand_path("fixtures", TEST_DIR)
7 | require File.expand_path("lib/jekyll-opal.rb", PROJECT_DIR)
8 |
9 | RSpec.configure do |config|
10 | # These two settings work together to allow you to limit a spec run
11 | # to individual examples or groups you care about by tagging them with
12 | # `:focus` metadata. When nothing is tagged with `:focus`, all examples
13 | # get run.
14 | config.filter_run :focus
15 | config.run_all_when_everything_filtered = true
16 |
17 | # Many RSpec users commonly either run the entire suite or an individual
18 | # file, and it's useful to allow more verbose output when running an
19 | # individual spec file.
20 | if config.files_to_run.one?
21 | # Use the documentation formatter for detailed output,
22 | # unless a formatter has already been configured
23 | # (e.g. via a command-line flag).
24 | config.default_formatter = 'doc'
25 | end
26 |
27 | # Print the 10 slowest examples and example groups at the
28 | # end of the spec run, to help surface which specs are running
29 | # particularly slow.
30 | config.profile_examples = 3
31 |
32 | # Run specs in random order to surface order dependencies. If you find an
33 | # order dependency and want to debug it, you can fix the order by providing
34 | # the seed, which is printed after each run.
35 | # --seed 1234
36 | config.order = :random
37 |
38 | # Seed global randomization in this process using the `--seed` CLI option.
39 | # Setting this allows you to use `--seed` to deterministically reproduce
40 | # test failures related to randomization by passing the same `--seed` value
41 | # as the one that triggered the failure.
42 | Kernel.srand config.seed
43 |
44 | # rspec-expectations config goes here. You can use an alternate
45 | # assertion/expectation library such as wrong or the stdlib/minitest
46 | # assertions if you prefer.
47 | config.expect_with :rspec do |expectations|
48 | # Enable only the newer, non-monkey-patching expect syntax.
49 | # For more details, see:
50 | # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
51 | expectations.syntax = :expect
52 | end
53 |
54 | # rspec-mocks config goes here. You can use an alternate test double
55 | # library (such as bogus or mocha) by changing the `mock_with` option here.
56 | config.mock_with :rspec do |mocks|
57 | # Enable only the newer, non-monkey-patching expect syntax.
58 | # For more details, see:
59 | # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
60 | mocks.syntax = :expect
61 |
62 | # Prevents you from mocking or stubbing a method that does not exist on
63 | # a real object. This is generally recommended.
64 | mocks.verify_partial_doubles = true
65 | end
66 |
67 | def jekyll_conf(overrides = {})
68 | Jekyll::Utils.deep_merge_hashes(
69 | Jekyll::Configuration::DEFAULTS,
70 | overrides
71 | )
72 | end
73 |
74 | def fixture_site
75 | Jekyll::Site.new jekyll_conf({
76 | "source" => source_dir,
77 | "destination" => dest_dir
78 | })
79 | end
80 |
81 | def source_dir(*files)
82 | test_dir("source", *files)
83 | end
84 |
85 | def dest_dir(*files)
86 | test_dir("dest", *files)
87 | end
88 |
89 | def test_dir(*files)
90 | File.join(TEST_DIR, *files)
91 | end
92 | end
93 |
--------------------------------------------------------------------------------