diff --git a/Gemfile b/Gemfile
index b807ce4..6e65c51 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,7 +1,5 @@
source 'http://rubygems.org'
-ruby "2.3.3"
-
gem 'rack'
gem 'webrick'
gem 'radius'
diff --git a/Gemfile.lock b/Gemfile.lock
index d8bb020..3966231 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -87,8 +87,5 @@ DEPENDENCIES
wannabe_bool
webrick
-RUBY VERSION
- ruby 2.3.3p222
-
BUNDLED WITH
- 1.14.6
+ 1.15.4
diff --git a/README.md b/README.md
index 17b0951..4a1a848 100644
--- a/README.md
+++ b/README.md
@@ -136,19 +136,20 @@ files: # files contains all the data fo
- ...
blog: # blog contains all the data for the tags
- name: String # -- accepts a string
+ - id: Integer
+ name: String # -- accepts a string
# blog articles much like pages are a repeating group of content for each article
- articles: # each article is seperated by a dash
- - article: # loops can access the following data in a
- name: String # -- accepts a string
- title: String # -- accepts a string
- created_by: # -- accepts two other objects
- first_name: String # -- accepts a string
- last_name: String # -- acccpts a string
- content: String # -- accepts a string or | pipe character followed by HTML
- published_at: 2 days ago # -- accepts a date string
- - article:
- ...
- - article:
- ...
+ articles: # each article is seperated by a dash
+ - article: # loops can access the following data in a
+ name: String # -- accepts a string
+ title: String # -- accepts a string
+ created_by: # -- accepts two other objects
+ first_name: String # -- accepts a string
+ last_name: String # -- acccpts a string
+ content: String # -- accepts a string or | pipe character followed by HTML
+ published_at: 2 days ago # -- accepts a date string
+ - article:
+ ...
+ - article:
+ ...
```
diff --git a/hammer/config/hammer b/hammer/config/hammer
new file mode 100644
index 0000000..6196072
--- /dev/null
+++ b/hammer/config/hammer
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/hammer/hammer_server.rb b/hammer/hammer_server.rb
index 19af560..2db9564 100644
--- a/hammer/hammer_server.rb
+++ b/hammer/hammer_server.rb
@@ -67,24 +67,37 @@ def os
end
-g = Git.open("../")
+# g = Git.open("../")
+hammer_branch_cmd = "cd ../ && git symbolic-ref --short HEAD"
+
begin
- branch = g.lib.send(:command, "symbolic-ref --short HEAD")
- ref = g.lib.send(:command, "rev-parse #{branch}")
- remote = g.lib.send(:command, "rev-parse origin/#{branch}")
+ hammer_branch = `#{hammer_branch_cmd}`
+ hammer_ref_cmd = "cd ../ && git rev-parse #{hammer_branch}"
+ hammer_remote_cmd = "cd ../ && git ls-remote"
+ hammer_ref = `#{hammer_ref_cmd}`
+ hammer_remote = `#{hammer_remote_cmd}`
+
+ hammer_branch = hammer_branch.delete("\n")
+ hammer_ref = hammer_ref.delete("\n")
+
+ hammer_remote = hammer_remote.split("\n").collect{|ref| ref.split("\t")}
+ hammer_remote = hammer_remote.select{|remote| remote[1] == "refs/heads/#{hammer_branch}"}[0][0]
+
+ puts "Hammer is on branch: ".colorize(:light_white)+"#{hammer_branch}".colorize(:light_blue)
+ puts "Hammer Local #{hammer_branch} branch ref is at: ".colorize(:light_white)+"#{hammer_ref}".colorize(:light_blue)
+ puts "Hammer Remote #{hammer_branch} branch ref is at: ".colorize(:light_white)+"#{hammer_remote}".colorize(:light_blue)
- if ref.to_s != remote.to_s
+ # branch = g.lib.send(:command, "symbolic-ref --short HEAD")
+ # ref = g.lib.send(:command, "rev-parse #{branch}")
+ # remote = g.lib.send(:command, "rev-parse origin/#{branch}")
+
+ if hammer_ref != hammer_remote
update_url = "https://github.com/wvuweb/hammer/wiki/Update"
puts " "
puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".colorize(:red)
puts "!!!".colorize(:red)+" WARNING YOU ARE BEHIND ON HAMMER VERSIONS".colorize(:light_cyan)+" !!!".colorize(:red)
puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".colorize(:red)
puts " "
- puts "Repository is currently at ref: ".colorize(:light_white)+(ref.to_s+" ").colorize(:light_magenta)
- puts "Remote is currently at ref: ".colorize(:light_white)+(remote.to_s+" ").colorize(:light_magenta)
- # puts "Learn how to update Hammer at: ".colorize(:light_white)+update_url.colorize(:light_cyan)
- puts " "
- puts " "
puts "Update Hammer by using using the following command: ".colorize(:light_white)
puts " "
puts "vagrant hammer update".colorize(:light_green)
@@ -93,7 +106,7 @@ def os
puts " "
puts " "
end
-rescue
+rescue => e
puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".colorize(:red)
puts "!!!".colorize(:red)+" COULD NOT CHECK HAMMER REPOSITORY FOR UPDATES".colorize(:light_cyan)+" !!!".colorize(:red)
puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".colorize(:red)
@@ -103,10 +116,27 @@ def os
doc_root = options.directory
if File.directory?(doc_root+"/code")
- code = Git.open(doc_root+"/code")
+ # code = Git.open(doc_root+"/code")
+
+ # Add identity files for bitbucket
+ File.chmod(0600,"./config/hammer")
+
+ puts "Adding Identity files to be able to access Code repository in bitbucket"
+ code_ref_cmd = " ssh-agent bash -c 'ssh-add ./config/hammer; cd #{doc_root+'/code'} && git rev-parse master'"
+ code_remote_cmd = "ssh-agent bash -c 'ssh-add ./config/hammer; cd #{doc_root+'/code'} && git ls-remote'"
+
begin
- code_ref = g.lib.send(:command, "rev-parse master")
- code_remote = g.lib.send(:command, "rev-parse origin/master")
+
+ code_ref = `#{code_ref_cmd}`
+ code_ref = code_ref.delete("\n")
+ code_remote = `#{code_remote_cmd}`
+ code_remote = code_remote.split("\n").collect{|ref| ref.split("\t")}.select{|remote| remote[1] == "refs/heads/master"}[0][0]
+
+ puts "Code Local repo ref is at: ".colorize(:light_white)+"#{code_ref}".colorize(:light_blue)
+ puts "Code Remote repo ref is at: ".colorize(:light_white)+"#{code_remote}".colorize(:light_blue)
+
+ #code_ref = g.lib.send(:command, "rev-parse master")
+ #code_remote = g.lib.send(:command, "rev-parse origin/master")
if code_ref.to_s != code_remote.to_s
puts " "
diff --git a/hammer/services/tag_container.rb b/hammer/services/tag_container.rb
index e0b937e..0c23ddf 100644
--- a/hammer/services/tag_container.rb
+++ b/hammer/services/tag_container.rb
@@ -3,6 +3,12 @@
require 'action_view'
require 'active_support/core_ext/string/output_safety'
+require '../hammer/services/theme_asset_pipeline/parser.rb'
+require '../hammer/services/theme_asset_pipeline/image.rb'
+require '../hammer/services/theme_asset_pipeline/javascript.rb'
+require '../hammer/services/theme_asset_pipeline/resource.rb'
+require '../hammer/services/theme_asset_pipeline/style.rb'
+
class TagContainer
def self.tag(name, &block)
diff --git a/hammer/services/tags/basic.rb b/hammer/services/tags/basic.rb
index e653fdf..57885ff 100644
--- a/hammer/services/tags/basic.rb
+++ b/hammer/services/tags/basic.rb
@@ -108,7 +108,6 @@ class Basic < TagContainer
# options['mode'] = tag.globals.mode
#
# %w(no_self no_root text_only reverse).each do |i|
- # binding.pry
# options[i] = options[i].to_b
# end
if tag.globals.context.data && tag.globals.context.data[:breadcrumbs]
@@ -456,11 +455,13 @@ def self.parse_date(str)
# cache [tag.cache_key, tag.globals.site, tag.globals.page], expires_in: cache_term_minutes.minutes do
begin
- url = url = URI.parse(url)
- request = req = Net::HTTP::Get.new(url.to_s)
- response = Net::HTTP.start(url.host, url.port) {|http|
- http.request(req)
- }
+ uri = URI.parse(url)
+ response = Net::HTTP.start(uri.host, uri.port,
+ :use_ssl => uri.scheme == 'https') do |http|
+ request = Net::HTTP::Get.new uri
+ http.request request # Net::HTTPResponse object
+ end
+
#rescue raise(RuntimeTagError, "ERROR: Could not load the XML URL: #{url}")
rescue => e
return Hammer.error "Could not load the XML URL: #{url} due to #{e}"
diff --git a/hammer/services/tags/blog.rb b/hammer/services/tags/blog.rb
index 3fd742f..03fce8a 100644
--- a/hammer/services/tags/blog.rb
+++ b/hammer/services/tags/blog.rb
@@ -23,7 +23,13 @@ class Blog < TagContainer
# tag.locals.blog ||= load_blog(tag)
# tag.expand
if tag.globals.context.data && tag.globals.context.data['blog']
- tag.locals.blog = tag.globals.context.data['blog']
+ if tag.attr['id'] && tag.globals.context.data['blog'].class == Array
+
+ @blog = tag.globals.context.data['blog'].select{|w,v| w['id'].to_s ==(tag.attr['id']) }.first
+ else
+
+ @blog = tag.globals.context.data['blog'].first
+ end
end
tag.expand
end
@@ -93,14 +99,18 @@ class Blog < TagContainer
# tag.locals.blog ||= load_blog(tag)
# tag.locals.articles = filter_articles(tag, tag.locals.blog.children.published)
# tag.expand
+ # if tag.globals.context.data && tag.globals.context.data[:blog]
- if tag.globals.context.data && tag.globals.context.data[:blog] && tag.globals.context.data[:blog][:articles]
- tag.locals.articles = tag.globals.context.data[:blog][:articles]
+ begin
+ tag.locals.articles = @blog[:articles]
+ # end
+ tag.locals.articles = [] if tag.locals.articles.nil?
+ tag.locals.attributes = tag.attr
+ tag.expand
+ rescue
+ Hammer.error 'Blog Articles should be part of an array.'
end
- tag.locals.articles = [] if tag.locals.articles.nil?
- tag.locals.attributes = tag.attr
- tag.expand
end
tag 'articles:each' do |tag|
@@ -179,8 +189,8 @@ class Blog < TagContainer
)
ActionView::Base.new.content_tag :ul, class: options[:ul_class] do
- if tag.globals.context.data[:blog][:archive] && tag.globals.context.data[:blog][:archive][:monthly] && tag.globals.context.data[:blog][:archive][:monthly].count > 0
- data = tag.globals.context.data[:blog][:archive][:monthly]
+ if @blog[:archive] && @blog[:archive][:monthly] && @blog[:archive][:monthly].count > 0
+ data = @blog[:archive][:monthly]
else
date_to = Date.parse(Chronic.parse('today').strftime("%Y-%m-%d").to_s)
date_from = Date.parse(Chronic.parse('4 months ago').strftime("%Y-%m-%d").to_s)
@@ -246,10 +256,8 @@ def load_blog(tag)
end
def load_article(tag)
- # page = tag.globals.page
- #page.type == 'ArticlePage' ? decorated_page(page) : nil
- if tag.globals.context.data && tag.globals.context.data['blog'] && tag.globals.context.data['blog']['articles']
- tag.globals.context.data['blog']['articles'].first
+ if tag.globals.context.data && tag.globals.context.data['blog'] && tag.globals.context.data['blog'].first['articles']
+ tag.globals.context.data['blog'].first['articles'].sample
else
content = <<-CONTENT
#{Faker::Lorem.paragraph(2)}
@@ -261,7 +269,7 @@ def load_article(tag)
:title => Faker::Lorem.sentence(1),
:created_by => { :first_name => Faker::Name.first_name, :last_name => Faker::Name.last_name },
:content => content,
- :published_at => Random.rand(11).to_s+ "days ago"
+ :published_at => Random.rand(11).to_s+ " days ago"
}
tag.locals.article = article
article
@@ -300,7 +308,6 @@ def loop_over(tag, target)
# end
#
# output.flatten.join('')
-
if tag.locals.attributes['limit']
limit = tag.locals.attributes['limit'].to_i - 1
items = target[0..limit]
diff --git a/hammer/services/tags/page.rb b/hammer/services/tags/page.rb
index 5c39ffd..5af16ed 100644
--- a/hammer/services/tags/page.rb
+++ b/hammer/services/tags/page.rb
@@ -166,12 +166,20 @@ class Page < TagContainer
if tag.globals.context.data && tag.globals.context.data['pages']
data = tag.globals.context.data['pages'].find { |h| h['id'] == tag.attr['id'].to_i }
+
+ puts "Processing tag get_page with page id #{data["id"]}".colorize(:light_blue)
+
oldcontext = tag.globals.context.data['page']
+
if data
newcontext = data
tag.expand(newcontext,oldcontext)
else
- Hammer.error "key pages:id of #{tag.attr['id']} not found in mock_data file"
+ if tag.attr['id'].nil
+ Hammer.error "get_page tag attribute of id is nil"
+ else
+ Hammer.error "key pages:id of: #{tag.attr['id']} was not found in mock_data file"
+ end
end
else
Hammer.error "Set key pages in mock_data file"
@@ -196,7 +204,7 @@ class Page < TagContainer
tag.expand unless tag.globals.context.data['page']['default_page']
end
- [:id, :name, :path, :slug, :meta_description, :title, :alternate_name, :depth, :created_at, :updated_at, :published_at].each do |attr|
+ [:id, :name, :path, :slug, :meta_description, :title, :alternate_name, :depth].each do |attr|
tag "page:#{attr.to_s}" do |tag|
# tag.locals.page.send(attr)
#{"}fix page:#{attr.to_s} tag"
@@ -208,6 +216,18 @@ class Page < TagContainer
end
end
+ [:created_at, :updated_at, :published_at].each do |attr|
+ tag "page:#{attr.to_s}" do |tag|
+ # tag.locals.page.send(attr)
+ #{"}fix page:#{attr.to_s} tag"
+ if tag.globals.context.data && tag.globals.context.data['page'] && tag.globals.context.data['page'][attr.to_s]
+ tag.globals.context.data['page'][attr.to_s]
+ else
+ Random.rand(11).to_s+ " days ago"
+ end
+ end
+ end
+
tag 'page:url' do |tag|
# format = tag.attr['format'].to_s.strip
# format = nil if format.downcase =~ /\Ahtml?\Z/
@@ -270,7 +290,6 @@ class Page < TagContainer
else
Hammer.error "Set key page in mock_data file"
end
- #binding.pry#"fix page:first_non_blank_attr tag"
end
tag 'page:content' do |tag|
@@ -310,7 +329,6 @@ class Page < TagContainer
# tag.locals.page_template = tag.locals.page.template
# tag.expand
if tag.globals.context.data && tag.globals.context.data["page"]
- # binding.pry
if tag.globals.context.data["page"]["template"]
tag.locals.page_template = tag.globals.context.data["page"]["template"]
end
diff --git a/hammer/services/tags/theme_asset.rb b/hammer/services/tags/theme_asset.rb
index d0e8480..02bf360 100644
--- a/hammer/services/tags/theme_asset.rb
+++ b/hammer/services/tags/theme_asset.rb
@@ -34,6 +34,13 @@ class ThemeAsset < TagContainer
output
end
+ tag 'stylesheet_content' do |tag|
+ css_name = tag.attr['name'].strip
+ css_name += '.css' unless css_name.ends_with?('.css')
+ pipe = ThemeAssetPipeline::Style.new(tag.globals.context.theme_root, css_name)
+ pipe.content
+ end
+
tag 'stylesheet_url' do |tag|
doc_root = tag.globals.context.server.config[:DocumentRoot]
diff --git a/hammer/services/theme_asset_pipeline/image.rb b/hammer/services/theme_asset_pipeline/image.rb
new file mode 100644
index 0000000..d051958
--- /dev/null
+++ b/hammer/services/theme_asset_pipeline/image.rb
@@ -0,0 +1,19 @@
+module ThemeAssetPipeline
+ class Image
+ attr_reader :theme, :last_modified, :etag, :file_path
+
+ def initialize(theme, request_path)
+ @request_path = request_path
+ @theme = theme
+
+ @file_path = @theme.image_path(@request_path)
+
+ raise Slate::Errors::FileNotFound unless File.exists?(@file_path)
+ @last_modified = File.mtime(@file_path).utc
+ end
+
+ def etag
+ @theme.updated_at
+ end
+ end
+end
diff --git a/hammer/services/theme_asset_pipeline/javascript.rb b/hammer/services/theme_asset_pipeline/javascript.rb
new file mode 100644
index 0000000..fef08cc
--- /dev/null
+++ b/hammer/services/theme_asset_pipeline/javascript.rb
@@ -0,0 +1,52 @@
+module ThemeAssetPipeline
+ class Javascript < Parser
+ def compile(file_path)
+ cfilename = compiled_filename(file_path)
+
+ if File.exists?(cfilename)
+ content = File.read(cfilename)
+ else
+ theme_config = theme.config
+ compress = theme_config['js']['compress']
+ mangle = theme_config['js']['mangle']
+
+ ext = File.extname(file_path).gsub(/^\./, '')
+ content = File.read(file_path)
+
+ # Compile CoffeeScript, if needed.
+ begin
+ content = CoffeeScript.compile(content) if ext == 'coffee'
+ rescue Exception => e
+ raise Slate::Errors::ThemeJavascript.new(e.message)
+ end
+
+ # Compress and mangle, if needed.
+ content = Uglifier.compile(content, :squeeze => compress, :mangle => mangle) if compress || mangle
+
+ # Write the compiled result to a new file
+ File.write(cfilename, content)
+
+ # Cleanup old compiled files
+ Dir.glob("#{file_path}.[0-9]*").each {|f| File.delete(f) unless f == cfilename }
+ end
+
+ content
+ end
+
+ def content
+ all_content = []
+ @file_paths.each { |file| all_content << compile(file) }
+ all_content.join("\n")
+ end
+
+ def content_type
+ 'text/javascript'
+ end
+
+ private
+
+ def load_paths
+ [theme.javascript_dir]
+ end
+ end
+end
diff --git a/hammer/services/theme_asset_pipeline/parser.rb b/hammer/services/theme_asset_pipeline/parser.rb
new file mode 100644
index 0000000..cab1b1f
--- /dev/null
+++ b/hammer/services/theme_asset_pipeline/parser.rb
@@ -0,0 +1,51 @@
+module ThemeAssetPipeline
+ class Parser
+ attr_reader :theme, :last_modified, :etag
+
+ def initialize(theme, request_path, options = {})
+ @request_path = request_path
+ @theme = theme
+ @options = options
+
+ parse_asset_files
+ end
+
+ def is_map_resource?
+ File.extname(@request_path).to_s.downcase == '.map'
+ end
+
+ def file_path
+ path = @file_paths.first
+ raise Slate::Errors::FileNotFound unless path.present? and File.exists?(path)
+ path
+ end
+
+ protected
+
+ def parse_asset_files
+ files = @request_path.split('&')
+ @file_paths = []
+ # @etag = @last_modified = @theme.updated_at
+ files.each do |file|
+ paths = load_paths.map { |path| File.join(path, file) }
+
+ if file_path = find_file(paths)
+ @file_paths << file_path
+ end
+ end
+ end
+
+ def find_file(paths)
+ paths = [paths] unless Array === paths
+ paths.map do |path|
+ return path if File.exists?(path)
+ Dir.glob(path + '*')
+ end.flatten.first
+ end
+
+ def compiled_filename(file)
+ #file + ".#{@theme.url_fingerprint}"
+ file
+ end
+ end
+end
diff --git a/hammer/services/theme_asset_pipeline/resource.rb b/hammer/services/theme_asset_pipeline/resource.rb
new file mode 100644
index 0000000..0a608be
--- /dev/null
+++ b/hammer/services/theme_asset_pipeline/resource.rb
@@ -0,0 +1,19 @@
+module ThemeAssetPipeline
+ class Resource
+ attr_reader :theme, :last_modified, :etag, :file_path
+
+ def initialize(theme, request_path)
+ @request_path = request_path
+ @theme = theme
+
+ @file_path = @theme.resource_path(@request_path)
+
+ raise Slate::Errors::FileNotFound unless File.exists?(@file_path)
+ @last_modified = File.mtime(@file_path).utc
+ end
+
+ def etag
+ @theme.updated_at
+ end
+ end
+end
diff --git a/hammer/services/theme_asset_pipeline/style.rb b/hammer/services/theme_asset_pipeline/style.rb
new file mode 100644
index 0000000..9b9335b
--- /dev/null
+++ b/hammer/services/theme_asset_pipeline/style.rb
@@ -0,0 +1,73 @@
+module ThemeAssetPipeline
+ class Style < Parser
+ def compile(file)
+ cfilename = compiled_filename(file)
+ if File.exists?(cfilename)
+ css = File.read(cfilename)
+ else
+ # Compile the given file
+ begin
+ css = Sass::Engine.new(File.read(file), :syntax => syntax(file), :style => style, :load_paths => load_paths).render
+ rescue Sass::SyntaxError => e
+ raise Slate::Errors::ThemeCSS.new(e.message)
+ end
+
+ # Write the compiled result to a new file
+ File.write(cfilename, css)
+
+ # Cleanup old compiled files
+ Dir.glob("#{file}.[0-9]*").each {|f| File.delete(f) unless f == cfilename }
+ end
+
+ css
+ end
+
+ def content
+ all_content = ""
+ @file_paths.each { |file| all_content.concat(compile(file)) }
+ all_content
+ # process_image_urls all_content
+ end
+
+ def content_type
+ 'text/css'
+ end
+
+ private
+
+ # This method will replace all theme image references with a properly
+ # formatted and versioned URL.
+ #
+ # Example:
+ #
+ # background: url(../images/flying-wv-w-signature.png) left 1px no-repeat;
+ #
+ # will be replaced with
+ #
+ # background: url(/images/1234567/flying-wv-w-signature.png) left 1px no-repeat;
+ #
+ # def process_image_urls(content)
+ # base_url = @options[:base_url] || ''
+ # content.gsub(/url\(\s*["']?(?:\.\.)?\/(images|public)\/(.*?)["']?\)/, "url(\"#{base_url}/\\1/#{@theme.url_fingerprint}/\\2\")")
+ # end
+
+ def syntax(file)
+ ext = File.extname(file).gsub(/^\./, '')
+ if %w(sass scss).include?(ext)
+ ext.to_sym
+ elsif ext == 'css'
+ :scss
+ end
+ end
+
+ def style
+ compress = theme.config['css']['compress']
+ compress ? :compressed : :expanded
+ end
+
+ def load_paths
+ # Pathname.new([@theme,'stylesheets'].join('/'))
+ [File.join(@theme, 'stylesheets')]
+ end
+ end
+end