Skip to content

Commit

Permalink
Allow to switch used Jade/Pug version!
Browse files Browse the repository at this point in the history
  • Loading branch information
yivo committed Jul 30, 2017
1 parent bcc68bf commit 63ff821
Show file tree
Hide file tree
Showing 35 changed files with 1,005 additions and 257 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ pkg/
tmp/
/.idea/
/node_modules/
/.yardoc/
/doc/
65 changes: 65 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
Style/StringLiterals:
EnforcedStyle: double_quotes

Metrics/LineLength:
Enabled: false
Max: 110

Style/FileName:
Regex: !ruby/regexp /\A[-a-z0-9]+\z/

Layout/CaseIndentation:
EnforcedStyle: end

Layout/AccessModifierIndentation:
EnforcedStyle: outdent

Layout/SpaceInsideArrayPercentLiteral:
Enabled: false

Layout/EmptyLinesAroundClassBody:
Enabled: false

Style/PerlBackrefs:
Enabled: false

Bundler/OrderedGems:
Enabled: false

Metrics/BlockLength:
Enabled: false

Style/EmptyMethod:
Enabled: false

Lint/UselessAssignment:
Enabled: false

Lint/EndAlignment:
EnforcedStyleAlignWith: variable

Lint/UnusedBlockArgument:
Enabled: false

Metrics/MethodLength:
Max: 20

Layout/ExtraSpacing:
Enabled: false
AllowForAlignment: true
ForceEqualSignAlignment: true

Style/PercentLiteralDelimiters:
PreferredDelimiters:
default: '[]'
'%i': '[]'
'%': '{}'

Layout/AlignParameters:
Enabled: false

Lint/UnusedMethodArgument:
Enabled: false

Style/StringLiteralsInInterpolation:
EnforcedStyle: double_quotes
4 changes: 4 additions & 0 deletions .yardopts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--protected
--private
-
lib/**/*.rb
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# encoding: UTF-8
# frozen_string_literal: true

source 'https://rubygems.org'
source "https://rubygems.org"

gemspec

gem 'test-unit', '~> 3.1', require: 'test/unit'
gem "test-unit", "~> 3.1", require: "test/unit"
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ PATH
remote: .
specs:
pug-ruby (1.0.2)
execjs (~> 2.0)
memoist (~> 0.15)
regexp-match-polyfill (~> 1.0)

GEM
remote: https://rubygems.org/
specs:
execjs (2.7.0)
memoist (0.16.0)
power_assert (1.0.2)
rake (10.5.0)
regexp-match-polyfill (1.0.1)
test-unit (3.2.5)
power_assert

Expand Down
4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ namespace "javascripts" do
require "open3"

def run(*args)
puts *args
puts(*args)
stdout, stderr, exit_status = Open3.capture3(*args)
fail stderr.strip.empty? ? stdout : stderr unless exit_status.success?
fail stderr.strip.empty? ? stdout : stderr unless exit_status.success?
stdout
end

Expand Down
116 changes: 116 additions & 0 deletions lib/jade-pug/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# encoding: UTF-8
# frozen_string_literal: true

require "memoist"

module JadePug
extend Memoist

#
# Compiles the template.
#
# @param source [String, #read]
# @param options [Hash]
# @return [String]
def compile(source, options = {})
compiler(@version).compile(source, options)
end

#
# Returns engine compiler for given version.
# Compilers are cached.
#
# @param version [String, :system]
# @return [Jade::SystemCompiler, Jade::ShippedCompiler, Pug::SystemCompiler, Pug::ShippedCompiler]
def compiler(version = @version)
(@compilers ||= {})["#{name}-#{version}"] ||= begin
case version
when :system then self::SystemCompiler.new
else self::ShippedCompiler.new(version)
end
end
end

#
# Switches compiler version.
#
# - If you want to switch compiler to one of that shipped with gem simple pass version as a string.
# - If you want to switch compiler to system pass :system as a version.
#
# Pass block to temporarily switch the version. Without block the version is switched permanently.
#
# @param wanted_version [String, :system]
# @return [void]
def use(wanted_version)
previous_version = @version
@version = wanted_version
did_switch_version(previous_version, wanted_version)

if block_given?
begin
yield
ensure
@version = previous_version
did_switch_version(wanted_version, previous_version)
end
end
end

#
# Executed after compiler version switched.
# Outputs some useful information about version being used.
#
# @param version_from [String, :system]
# @param version_to [String, :system]
# @return [void]
def did_switch_version(version_from, version_to)
if version_from != version_to
if Symbol === version_to
puts "Using #{version_to} #{name}."
else
puts "Using #{name} #{version_to}. NOTE: Advanced features like includes, extends and blocks will not work."
end
end
nil
end

#
# Returns the list of all available engine compiler versions shipped with gem.
#
# @return [Array<String>]
def versions
Dir[File.expand_path("../../../vendor/assets/javascripts/**/#{name.downcase}-*.js", __FILE__)].map do |path|
File.basename(path).match(/\A#{name.downcase}-(?!runtime-)(?<v>.+)\.min\.js\z/)&.send(:[], :v)
end.compact.sort
end
memoize :versions

#
# Returns the list of all available engine runtime versions shipped with gem.
#
# @return [Array<String>]
def runtime_versions
Dir[File.expand_path("../../../vendor/assets/javascripts/**/#{name.downcase}-*.js", __FILE__)].map do |path|
File.basename(path).match(/\A#{name.downcase}-runtime-(?<v>.+)\.js\z/)&.send(:[], :v)
end.compact.sort
end
memoize :runtime_versions

#
# Returns version for system-wide installed engine compiler.
#
# @return [String]
def system_version
compiler(:system).version
end

#
# Returns config object for engine.
# Executed only once per engine (return value is memoized).
#
# @return [Jade::Config, Pug::Config]
def config
self::Config.new
end
memoize :config
end
91 changes: 91 additions & 0 deletions lib/jade-pug/compiler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# encoding: UTF-8
# frozen_string_literal: true

module JadePug
#
# Abstraction layer for engine compiler.
#
class Compiler

#
# Returns the engine module.
#
# Used in such cases:
# - used to compute the name for engine
# - used to refer to the error classes
#
# @return [Jade, Pug]
attr_reader :engine

#
# Returns the version of engine compiler.
#
# @return [String]
attr_reader :version

#
# @param engine [Jade, Pug]
# @param version [String]
def initialize(engine, version)
@engine = engine
@version = version
end

#
# Compiles template.
#
# By default does nothing.
#
# @abstract Derived compilers must implement it.
# @param source [String, #read]
# The template source code or any object which responds to #read and returns string.
# @param options [Hash]
# @return [String]
def compile(source, options = {})

end

protected

#
# Reads the template source code.
# Responds for pre-processing source code.
# Actually, it just checks if source code responds to #read and if so
#
# @param source [String, #read]
# @return [String]
def prepare_source(source)
source.respond_to?(:read) ? source.read : source
end

#
# Responds for preparing compilation options.
#
# The next steps are executed:
# - is merges options into the engine config
# - it camelizes and symbolizes every option key
# - it removes nil values from the options
#
# @param options [Hash]
# @return [Hash]
def prepare_options(options)
options = engine.config.to_hash.merge(options)
options.keys.each { |k, v| options[k.to_s.gsub(/_([a-z])/) { $1.upcase }.to_sym] = options[k] }
options.delete_if { |k, v| v.nil? }
end

#
# Responds for post-processing compilation result.
#
# By default returns the result without any processing.
# Derived compilers may override it for it's own special behaviors.
#
# @param source [String] The source code of template.
# @param result [String] The compiled code of template.
# @param options [Hash] The compilation options.
# @return [String]
def process_result(source, result, options)
result
end
end
end
56 changes: 56 additions & 0 deletions lib/jade-pug/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# encoding: UTF-8
# frozen_string_literal: true

require "regexp-match-polyfill"

module JadePug
#
# Defines template engine compiler configuration.
#
class Config
#
# Allows to dynamically set config attributes.
#
def method_missing(name, *args, &block)
return super if block

case args.size
when 0

# config.client?
if name =~ /\A(\w+)\?\z/
!!(respond_to?($1) ? send($1) : instance_variable_get("@#{$1}"))

# config.client
elsif name =~ /\A(\w+)\z/
instance_variable_get("@#{$1}")

else
super
end

when 1
# config.client=
if name =~ /\A(\w+)=\z/
instance_variable_set("@#{$1}", args.first)
else
super
end
else
super
end
end

def respond_to_missing?(name, include_all)
name.match?(/\A\w+[=?]?\z/)
end

#
# Transforms config to the hash with all keys symbolized.
#
# @return [Hash]
def to_hash
instance_variables.map { |var| [var[1..-1].to_sym, instance_variable_get(var)] }.to_h
end
end
end
14 changes: 14 additions & 0 deletions lib/jade-pug/errors/compilation-error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# encoding: UTF-8
# frozen_string_literal: true

module JadePug
#
# Used for template compilation errors, for example:
# - any template engine errors
# - syntax errors in template
# - any JavaScript exceptions (they are caught by ExecJS)
#
class CompilationError < StandardError

end
end
Loading

0 comments on commit 63ff821

Please sign in to comment.