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