blade-0.7.1/ 0000755 0001750 0001750 00000000000 13425054107 013325 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/lib/ 0000755 0001750 0001750 00000000000 13425054107 014073 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/lib/blade.rb 0000644 0001750 0001750 00000005541 13425054107 015474 0 ustar utkarsh2102 utkarsh2102 require "active_support/all" require "eventmachine" require "faye" require "pathname" require "yaml" require "blade/version" require "blade/cli" module Blade extend self CONFIG_DEFAULTS = { framework: :qunit, port: 9876, build: { path: "." } } CONFIG_FILENAMES = %w( blade.yml .blade.yml ) @components = [] def register_component(component) @components << component end require "blade/component" require "blade/server" autoload :Model, "blade/model" autoload :Assets, "blade/assets" autoload :Config, "blade/config" autoload :RackAdapter, "blade/rack/adapter" autoload :RackRouter, "blade/rack/router" autoload :Session, "blade/session" autoload :TestResults, "blade/test_results" delegate :subscribe, :publish, to: Server attr_reader :config def start(options = {}) return if running? ensure_tmp_path initialize!(options) load_interface handle_exit EM.run do @components.each { |c| c.try(:start) } @running = true end end def stop return if @stopping @stopping = true @components.each { |c| c.try(:stop) } EM.stop if EM.reactor_running? @running = false end def running? @running end def initialize!(options = {}) return if @initialized @initialized = true options = CONFIG_DEFAULTS.deep_merge(blade_file_options).deep_merge(options) @config = Blade::Config.new options config.load_paths = Array(config.load_paths) config.logical_paths = Array(config.logical_paths) if config.build? config.build.logical_paths = Array(config.build.logical_paths) config.build.path ||= "." end config.plugins ||= {} load_requires load_plugins load_adapter end def build initialize! Assets.build end def url(path = "/") "http://#{Server.host}:#{config.port}#{path}" end def root_path Pathname.new(File.dirname(__FILE__)).join("../") end def tmp_path Pathname.new(".").join("tmp/blade") end def ensure_tmp_path tmp_path.mkpath end def clean_tmp_path tmp_path.rmtree if tmp_path.exist? end private def handle_exit at_exit do stop exit $!.status if $!.is_a?(SystemExit) end %w( INT ).each do |signal| trap(signal) { exit(1) } end end def blade_file_options if filename = CONFIG_FILENAMES.detect { |name| File.exists?(name) } YAML.load_file(filename) else {} end end def load_interface require "blade/interface/#{config.interface}" end def load_adapter require "blade/#{config.framework}_adapter" end def load_requires Array(config.require).each do |path| require path end end def load_plugins config.plugins.keys.each do |name| require "blade/#{name}_plugin" end end end blade-0.7.1/lib/blade/ 0000755 0001750 0001750 00000000000 13425054107 015142 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/lib/blade/test_results.rb 0000644 0001750 0001750 00000002106 13425054107 020226 0 ustar utkarsh2102 utkarsh2102 class Blade::TestResults STATUS_DOTS = { pass: ".", fail: "✗" }.with_indifferent_access attr_reader :session_id, :state, :results, :total, :failures def initialize(session_id) @session_id = session_id reset Blade.subscribe("/tests") do |details| if details[:session_id] == session_id event = details.delete(:event) try("process_#{event}", details) end end end def reset @results = [] @state = "pending" @total = 0 @failures = 0 end def process_begin(details) reset @state = "running" @total = details[:total] publish(total: @total) end def process_result(details) result = details.slice(:status, :name, :message) @results << result if result[:status] == "fail" @state = "failing" @failures += 1 end publish(result) end def process_end(details) @state = failures.zero? ? "finished" : "failed" publish(completed: true) end def publish(message = {}) Blade.publish("/results", message.merge(state: state, session_id: session_id)) end end blade-0.7.1/lib/blade/interface/ 0000755 0001750 0001750 00000000000 13425054107 017102 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/lib/blade/interface/ci.rb 0000644 0001750 0001750 00000002237 13425054107 020026 0 ustar utkarsh2102 utkarsh2102 module Blade::CI extend self include Blade::Component def start @completed_sessions = 0 @failures = [] Blade.subscribe("/results") do |details| process_result(details) end end private def process_result(details) if status = details[:status] STDOUT.print status_dot(status) if status == "fail" @failures << details end end if details[:completed] process_completion end end def process_completion @completed_sessions += 1 if done? EM.add_timer 2 do display_failures STDOUT.puts exit_with_status_code end end end def status_dot(status) Blade::TestResults::STATUS_DOTS[status] end def done? @completed_sessions == (Blade.config.expected_sessions || 1) end def display_failures @failures.each do |details| STDERR.puts "\n\n#{status_dot(details[:status])} #{details[:name]} (#{Blade::Session.find(details[:session_id])})" STDERR.puts details[:message] end end def exit_with_status_code exit @failures.any? ? 1 : 0 end end blade-0.7.1/lib/blade/interface/runner.rb 0000644 0001750 0001750 00000005031 13425054107 020737 0 ustar utkarsh2102 utkarsh2102 require "curses" module Blade::Runner extend self include Blade::Component autoload :Tab, "blade/interface/runner/tab" COLOR_NAMES = %w( white yellow green red ) PADDING = 1 def colors @colors ||= OpenStruct.new.tap do |colors| COLOR_NAMES.each do |name| const = Curses.const_get("COLOR_#{name.upcase}") Curses.init_pair(const, const, Curses::COLOR_BLACK) colors[name] = Curses.color_pair(const) end end end def create_window(options = {}) height = options[:height] || 0 width = options[:width] || 0 top = options[:top] || 0 left = options[:left] || PADDING parent = options[:parent] || Curses.stdscr parent.subwin(height, width, top, left) end def start run Blade::Assets.watch_logical_paths end def stop Curses.close_screen end def run start_screen init_windows handle_keys handle_stale_tabs Blade.subscribe("/results") do |details| session = Blade::Session.find(details[:session_id]) unless tab = Tab.find(session.id) tab = Tab.create(id: session.id) tab.activate if Tab.size == 1 end tab.draw Curses.doupdate end end private def start_screen Curses.init_screen Curses.start_color Curses.noecho Curses.curs_set(0) Curses.stdscr.keypad(true) end def init_windows header_window = create_window(height: 3) header_window.attron(Curses::A_BOLD) header_window.addstr "BLADE RUNNER [press 'q' to quit]\n" header_window.attroff(Curses::A_BOLD) header_window.addstr "Open #{Blade.url} to start" header_window.noutrefresh Tab.install(top: header_window.maxy) Curses.doupdate end def handle_keys EM.defer do while ch = Curses.getch case ch when Curses::KEY_LEFT Tab.active.try(:activate_previous) Curses.doupdate when Curses::KEY_RIGHT Tab.active.try(:activate_next) Curses.doupdate when "q" Blade.stop end end end end def handle_stale_tabs Blade.subscribe("/browsers") do |details| if details["message"] = "ping" if tab = Tab.find(details["session_id"]) tab.last_ping_at = Time.now end end end EM.add_periodic_timer(1) do Tab.stale.each { |t| remove_tab(t) } end end def remove_tab(tab) Tab.remove(tab.id) Curses.doupdate end end blade-0.7.1/lib/blade/interface/runner/ 0000755 0001750 0001750 00000000000 13425054107 020413 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/lib/blade/interface/runner/tab.rb 0000644 0001750 0001750 00000007135 13425054107 021514 0 ustar utkarsh2102 utkarsh2102 class Blade::Runner::Tab < Blade::Model delegate :colors, :create_window, to: Blade::Runner class << self delegate :create_window, to: Blade::Runner attr_reader :window, :state_window, :content_window def install(options = {}) top = options[:top] @window = create_window(top: top, height: 3) top = @window.begy + @window.maxy + 1 @state_window = create_window(top: top, height: 1) top = @state_window.begy + @state_window.maxy + 1 @content_window = create_window(top: top) @content_window.scrollok(true) end def draw window.clear window.noutrefresh all.each(&:draw) end def remove(id) tab = find(id) tab.deactivate tab.window.close super draw end def active all.detect(&:active?) end def stale threshold = Time.now - 2 all.select { |t| t.last_ping_at && t.last_ping_at < threshold } end end def tabs self.class end def height 3 end def width 5 end def top tabs.window.begy end def left tabs.window.begx + index * width end def window @window ||= create_window(height: height, width: width, top: top, left: left) end def draw window.clear active? ? draw_active : draw_inactive window.noutrefresh end def draw_active window.addstr "╔═══╗" window.addstr "║ " window.attron(color) window.addstr(dot) window.attroff(color) window.addstr(" ║") window.addstr "╝ ╚" draw_test_results end def draw_inactive window.addstr "\n" window.attron(color) window.addstr(" #{dot}\n") window.attroff(color) window.addstr "═════" end def draw_test_results tabs.content_window.clear failures = [] session.test_results.results.each do |result| tabs.content_window.addstr(status_dot(result)) failures << result if result[:status] == "fail" end failures.each do |result| tabs.content_window.addstr("\n\n") tabs.content_window.attron(Curses::A_BOLD) tabs.content_window.attron(colors.red) tabs.content_window.addstr("#{status_dot(result)} #{result[:name]}\n") tabs.content_window.attroff(colors.red) tabs.content_window.attroff(Curses::A_BOLD) tabs.content_window.addstr(result[:message]) end tabs.content_window.noutrefresh end def dot state == "pending" ? "○" : "●" end def status_dot(result) Blade::TestResults::STATUS_DOTS[result[:status]] end def index tabs.all.index(self) end def session Blade::Session.find(id) end def state session.test_results.state end def active? active end def activate return if active? if tab = tabs.active tab.deactivate end self.active = true draw tabs.state_window.addstr(session.to_s) tabs.state_window.noutrefresh end def deactivate return unless active? self.active = false draw tabs.state_window.clear tabs.state_window.noutrefresh tabs.content_window.clear tabs.content_window.noutrefresh end def activate_next all = tabs.all if all.last == self all.first.activate elsif tab = all[index + 1] tab.activate end end def activate_previous all = tabs.all if all.first == self all.last.activate elsif tab = all[index - 1] tab.activate end end def color case state when "running" then colors.yellow when "finished" then colors.green when /fail/ then colors.red else colors.white end end end blade-0.7.1/lib/blade/session.rb 0000644 0001750 0001750 00000000643 13425054107 017155 0 ustar utkarsh2102 utkarsh2102 class Blade::Session < Blade::Model KEY = "blade_session" class << self def create(attributes) model = super model.test_results = Blade::TestResults.new(model.id) model end def combined_test_results Blade::CombinedTestResults.new(all) end end def to_s @to_s ||= "#{ua.browser} #{ua.version} #{ua.platform}" end private def ua user_agent end end blade-0.7.1/lib/blade/version.rb 0000644 0001750 0001750 00000000045 13425054107 017153 0 ustar utkarsh2102 utkarsh2102 module Blade VERSION = "0.7.1" end blade-0.7.1/lib/blade/server.rb 0000644 0001750 0001750 00000001513 13425054107 016775 0 ustar utkarsh2102 utkarsh2102 require "faye/websocket" require "useragent" module Blade::Server extend self include Blade::Component WEBSOCKET_PATH = "/blade/websocket" def start Faye::WebSocket.load_adapter("thin") Thin::Logging.silent = true Thin::Server.start(host, Blade.config.port, app, signals: false) end def host Thin::Server::DEFAULT_HOST end def websocket_url(path = "") Blade.url(WEBSOCKET_PATH + path) end def client @client ||= Faye::Client.new(websocket_url) end def subscribe(channel) client.subscribe(channel) do |message| yield message.with_indifferent_access end end def publish(channel, message) client.publish(channel, message) end private def app Rack::Builder.app do use Rack::ShowExceptions run Blade::RackAdapter.new end end end blade-0.7.1/lib/blade/rack/ 0000755 0001750 0001750 00000000000 13425054107 016062 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/lib/blade/rack/router.rb 0000644 0001750 0001750 00000001436 13425054107 017733 0 ustar utkarsh2102 utkarsh2102 module Blade::RackRouter extend ActiveSupport::Concern DEFAULT = :* included do cattr_accessor(:routes) { Hash.new } end class_methods do def route(path, action) pattern = /^\/?#{path.gsub(/\*/, ".*")}$/ base_path = path.match(/([^\*]*)\*?/)[1] routes[path] = { action: action, pattern: pattern, base_path: base_path } self.routes = routes.sort_by { |path, value| -path.size }.to_h routes[path] end def default_route(action) routes[DEFAULT] = { action: action } end def find_route(path) if route = routes.detect { |key, details| path =~ details[:pattern] } route[1] else routes[DEFAULT] end end end private def find_route(*args) self.class.find_route(*args) end end blade-0.7.1/lib/blade/rack/adapter.rb 0000644 0001750 0001750 00000003326 13425054107 020033 0 ustar utkarsh2102 utkarsh2102 class Blade::RackAdapter include Blade::RackRouter route "", to: :redirect_to_index route "/", to: :index route "/blade/websocket*", to: :websocket default_route to: :environment attr_reader :request, :env def initialize Blade.initialize! end def call(env) @env = env @request = Rack::Request.new(env) route = find_route(request.path_info) base_path, action = route.values_at(:base_path, :action) rewrite_path!(base_path) send(action[:to]) end def index request.path_info = "/blade/index.html" response = environment response = add_session_cookie(response) if needs_session_cookie? response.to_a end def redirect_to_index Rack::Response.new.tap do |response| path = request.path path = path + "/" unless path.last == "/" response.redirect(path) end.to_a end def websocket faye_adapter.call(env) end def environment Blade::Assets.environment.call(env) end private def needs_session_cookie? Blade.running? && !Blade::Session.find(request.cookies[Blade::Session::KEY]) end def add_session_cookie(response) user_agent = UserAgent.parse(request.user_agent) session = Blade::Session.create(user_agent: user_agent) status, headers, body = response response = Rack::Response.new(body, status, headers) response.set_cookie(Blade::Session::KEY, session.id) response end def rewrite_path!(path = nil) return if path.nil? request.path_info = request.path_info.sub(path, "").presence || "/" request.script_name = request.script_name + path end def faye_adapter @faye_adapter ||= Faye::RackAdapter.new(mount: "/", timeout: 25) end end blade-0.7.1/lib/blade/component.rb 0000644 0001750 0001750 00000000137 13425054107 017472 0 ustar utkarsh2102 utkarsh2102 module Blade::Component def self.included(base) Blade.register_component(base) end end blade-0.7.1/lib/blade/cli.rb 0000644 0001750 0001750 00000000655 13425054107 016244 0 ustar utkarsh2102 utkarsh2102 require "thor" class Blade::CLI < Thor desc "runner", "Start test runner in console mode" def runner Blade.start(interface: :runner) end desc "ci", "Start test runner in CI mode" def ci Blade.start(interface: :ci) end desc "build", "Build assets" def build Blade.build end desc "config", "Inspect Blade.config" def config require "pp" Blade.initialize! pp Blade.config end end blade-0.7.1/lib/blade/config.rb 0000644 0001750 0001750 00000000565 13425054107 016742 0 ustar utkarsh2102 utkarsh2102 class Blade::Config < ActiveSupport::HashWithIndifferentAccess def method_missing(method, *args) case method when /=$/ self[$`] = args.first when /\?$/ self[$`].present? else if self[method].is_a?(Hash) && !self[method].is_a?(self.class) self[method] = self.class.new(self[method]) end self[method] end end end blade-0.7.1/lib/blade/assets.rb 0000644 0001750 0001750 00000003622 13425054107 016774 0 ustar utkarsh2102 utkarsh2102 require "sprockets" module Blade::Assets autoload :Builder, "blade/assets/builder" extend self def environment @environment ||= Sprockets::Environment.new do |env| env.cache = Sprockets::Cache::FileStore.new(Blade.tmp_path) %w( blade user adapter ).each do |name| send("#{name}_load_paths").each do |path| env.append_path(path) end end env.context_class.class_eval do delegate :logical_paths, to: Blade::Assets end end end def build if Blade.config.build Builder.new(environment).build end end def logical_paths(type = nil) paths = Blade.config.logical_paths paths.select! { |path| File.extname(path) == ".#{type}" } if type paths end def blade_load_paths [ Blade.root_path.join("assets") ] end def user_load_paths Blade.config.load_paths.flat_map do |load_path| if load_path.is_a?(Hash) load_path.flat_map do |gem_name, paths| Array(paths).map{ |path| gem_pathname(gem_name).join(path) } end else Pathname.new(load_path) end end end def adapter_load_paths gem_name = "blade-#{Blade.config.framework}_adapter" [ gem_pathname(gem_name).join("assets") ] end def watch_logical_paths @mtimes = get_mtimes EM.add_periodic_timer(1) do mtimes = get_mtimes unless mtimes == @mtimes @mtimes = mtimes Blade.publish("/assets", changed: @mtimes) end end end private def get_mtimes {}.tap do |mtimes| Blade.config.logical_paths.each do |path| mtimes[path] = get_mtime(path) end end end def get_mtime(logical_path) environment[logical_path].mtime rescue Exception => e e.to_s end def gem_pathname(gem_name) gemspec = Gem::Specification.find_by_name(gem_name) Pathname.new(gemspec.gem_dir) end end blade-0.7.1/lib/blade/model.rb 0000644 0001750 0001750 00000000675 13425054107 016577 0 ustar utkarsh2102 utkarsh2102 require "securerandom" class Blade::Model < OpenStruct class << self def models @models ||= {} end def create(attributes) attributes[:id] ||= SecureRandom.hex(4) model = new(attributes) models[model.id] = model end def find(id) models[id] end def remove(id) models.delete(id) end def all models.values end def size models.size end end end blade-0.7.1/lib/blade/assets/ 0000755 0001750 0001750 00000000000 13425054107 016444 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/lib/blade/assets/builder.rb 0000644 0001750 0001750 00000003171 13425054107 020421 0 ustar utkarsh2102 utkarsh2102 class Blade::Assets::Builder attr_accessor :environment def initialize(environment) @environment = environment end def build puts "Building assets…" clean compile clean_dist_path create_dist_path install end private def compile environment.js_compressor = Blade.config.build.js_compressor.try(:to_sym) environment.css_compressor = Blade.config.build.css_compressor.try(:to_sym) manifest.compile(logical_paths) end def install logical_paths.each do |logical_path| fingerprint_path = manifest.assets[logical_path] source_path = compile_path.join(fingerprint_path) destination_path = dist_path.join(logical_path) FileUtils.cp(source_path, destination_path) puts "[created] #{destination_path}" end end def manifest @manifest ||= Sprockets::Manifest.new(environment.index, compile_path) end def clean compile_path.rmtree if compile_path.exist? compile_path.mkpath end def logical_paths Blade.config.build.logical_paths end def create_dist_path dist_path.mkpath unless dist_path.exist? end def clean_dist_path if clean_dist_path? children = dist_path.children dist_path.rmtree children.each do |child| puts "[removed] #{child}" end end end def clean_dist_path? Blade.config.build.clean && dist_path.exist? end def dist_path @dist_path ||= Pathname.new(Blade.config.build.path) end def compile_path @compile_path ||= Blade.tmp_path.join("compile") end end blade-0.7.1/Rakefile 0000644 0001750 0001750 00000000353 13425054107 014773 0 ustar utkarsh2102 utkarsh2102 require "rake" require "rake/testtask" require "bundler/gem_tasks" task default: :test Rake::TestTask.new(:test) do |t| t.libs << "test" t.pattern = "test/*_test.rb" t.verbose = true end Rake::Task[:test].comment = "Run tests" blade-0.7.1/LICENSE.txt 0000644 0001750 0001750 00000002071 13425054107 015150 0 ustar utkarsh2102 utkarsh2102 The MIT License (MIT) Copyright (c) 2016 Javan Makhmali Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. blade-0.7.1/exe/ 0000755 0001750 0001750 00000000000 13425054107 014106 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/exe/blade 0000755 0001750 0001750 00000000074 13425054107 015104 0 ustar utkarsh2102 utkarsh2102 #!/usr/bin/env ruby require "blade" Blade::CLI.start(ARGV) blade-0.7.1/blade.gemspec 0000644 0001750 0001750 00000002464 13425054107 015747 0 ustar utkarsh2102 utkarsh2102 # coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'blade/version' Gem::Specification.new do |spec| spec.name = "blade" spec.version = Blade::VERSION spec.authors = ["Javan Makhmali"] spec.email = ["javan@javan.us"] spec.summary = %q{Blade} spec.description = %q{Sprockets test runner and toolkit} spec.homepage = "https://github.com/javan/blade" spec.license = "MIT" spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.10" spec.add_development_dependency "rake", "~> 10.0" spec.add_dependency "blade-qunit_adapter", "~> 2.0.1" spec.add_dependency "activesupport", ">= 3.0.0" spec.add_dependency "coffee-script" spec.add_dependency "coffee-script-source" spec.add_dependency "curses", "~> 1.0.0" spec.add_dependency "eventmachine" spec.add_dependency "faye" spec.add_dependency "sprockets", ">= 3.0" spec.add_dependency "thin", ">= 1.6.0" spec.add_dependency "useragent", "~> 0.16.7" spec.add_dependency "thor", ">= 0.19.1" end blade-0.7.1/bin/ 0000755 0001750 0001750 00000000000 13425054107 014075 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/bin/rake 0000755 0001750 0001750 00000000554 13425054107 014751 0 ustar utkarsh2102 utkarsh2102 #!/usr/bin/env ruby # # This file was generated by Bundler. # # The application 'rake' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) require "rubygems" require "bundler/setup" load Gem.bin_path("rake", "rake") blade-0.7.1/bin/console 0000755 0001750 0001750 00000000512 13425054107 015463 0 ustar utkarsh2102 utkarsh2102 #!/usr/bin/env ruby require "bundler/setup" require "blade" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. # (If you use this, don't forget to add pry to your Gemfile!) # require "pry" # Pry.start require "irb" IRB.start blade-0.7.1/bin/setup 0000755 0001750 0001750 00000000163 13425054107 015163 0 ustar utkarsh2102 utkarsh2102 #!/bin/bash set -euo pipefail IFS=$'\n\t' bundle install # Do any other automated setup that you need to do here blade-0.7.1/README.md 0000644 0001750 0001750 00000004010 13425054107 014577 0 ustar utkarsh2102 utkarsh2102 # Blade ### A [Sprockets](https://github.com/rails/sprockets) Toolkit for Building and Testing JavaScript Libraries ## Getting Started Add Blade to your `Gemfile`. ```ruby source "https://rubygems.org" gem 'blade' ``` Create a `.blade.yml` (or `blade.yml`) file in your project’s root, and define your Sprockets [load paths](https://github.com/rails/sprockets#the-load-path) and [logical paths](https://github.com/rails/sprockets#logical-paths). Example: ```yaml # .blade.yml load_paths: - src - test/src - test/vendor logical_paths: - widget.js - test.js ``` ## Compiling Configure your build paths and [compressors](https://github.com/rails/sprockets#minifying-assets): ```yaml # .blade.yml … build: logical_paths: - widget.js path: dist js_compressor: uglifier # Optional ``` Run `bundle exec blade build` to compile `dist/widget.js`. ## Testing Locally By default, Blade sets up a test runner using [QUnit](http://qunitjs.com/) via the [blade-qunit_adapter](https://github.com/javan/blade-qunit_adapter) gem. Run `bundle exec blade runner` to launch Blade’s test console and open the URL it displays in one or more browsers. Blade detects changes to your logical paths and automatically restarts the test suite.  ## Testing on CI Run `bundle exec blade ci` to start Blade’s test console in non-interactive CI mode, and launch a browser pointed at Blade’s testing URL (usually http://localhost:9876). The process will return `0` on success and non-zero on failure. To test on multiple browsers with [Sauce Labs](https://saucelabs.com/), see the [Sauce Labs plugin](https://github.com/javan/blade-sauce_labs_plugin). ## Projects Using Blade * [Trix](https://github.com/basecamp/trix) * [Turbolinks](https://github.com/turbolinks/turbolinks) * [Action Cable](https://github.com/rails/rails/tree/master/actioncable) --- Licensed under the [MIT License](LICENSE.txt) © 2016 Javan Makhmali blade-0.7.1/.gitignore 0000644 0001750 0001750 00000000127 13425054107 015315 0 ustar utkarsh2102 utkarsh2102 /.bundle/ /.yardoc /Gemfile.lock /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ blade-0.7.1/Gemfile 0000644 0001750 0001750 00000000132 13425054107 014614 0 ustar utkarsh2102 utkarsh2102 source 'https://rubygems.org' # Specify your gem's dependencies in blade.gemspec gemspec blade-0.7.1/assets/ 0000755 0001750 0001750 00000000000 13425054107 014627 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/assets/blade/ 0000755 0001750 0001750 00000000000 13425054107 015676 5 ustar utkarsh2102 utkarsh2102 blade-0.7.1/assets/blade/index.coffee 0000644 0001750 0001750 00000001733 13425054107 020162 0 ustar utkarsh2102 utkarsh2102 @Blade = suiteDidBegin: ({total}) -> event = "begin" publish("/tests", {event, total}) testDidEnd: ({name, status, message}) -> event = "result" publish("/tests", {event, name, status, message}) suiteDidEnd: ({total}) -> event = "end" publish("/tests", {event, total}) publish = (channel, data = {}) -> client.publish(channel, copy(data, {session_id})) if session_id? copy = (object, withAttributes = {}) -> result = {} result[key] = value for key, value of object result[key] = value for key, value of withAttributes result getWebSocketURL = -> element = document.querySelector("script[data-websocket]") element.src.replace(/\/client\.js$/, "") getSessionId = -> document.cookie.match(/blade_session=(\w+)/)?[1] client = new Faye.Client(getWebSocketURL()) if session_id = getSessionId() client.subscribe "/assets", (data) -> location.reload() if data.changed setInterval -> publish("/browsers", event: "ping") , 1000 blade-0.7.1/assets/blade/index.html.erb 0000644 0001750 0001750 00000001521 13425054107 020441 0 ustar utkarsh2102 utkarsh2102