module Scms require "scms/version" require 'scms/scms-utils.rb' require 'scms/scms-helpers.rb' require 'scms/scms-pageoptions.rb' require 'scms/scms-bundler.rb' require 'scms/scms-parser.rb' require 'scms/scms-xmlhandler.rb' require 'scms/s3deploy.rb' require 'fileutils' require 'pathname' require 'erb' require 'ostruct' require 'yaml' require 'sass' require 'packr' require 'maruku' include YAML def Scms.getSettings(configdir) yamlpath=File.join(configdir, "_config.yml") settings = ScmsUtils.readyaml(yamlpath) if settings return settings else ScmsUtils.errLog("Config is empty") end end def Scms.build(website, settings, options) ScmsUtils.boldlog("Compiling #{website}") if settings #Bootstrap here if settings["bootstrap"] != nil bootstrap = File.join(website, settings["bootstrap"]) #ScmsUtils.log("Bootstrap is: #{settings["bootstrap"]}") if File.exists?(bootstrap) begin require_relative bootstrap rescue Exception=>e ScmsUtils.errLog(e.message) ScmsUtils.log(e.backtrace.inspect) end else ScmsUtils.errLog("Bootstrap does not exist #{settings["bootstrap"]}") ScmsUtils.writelog("::Bootstrap does not exist #{settings["bootstrap"]}", website) ScmsUtils.writelog("type NUL > #{bootstrap}", website) end end Scms.generatePages(website, settings, options) else ScmsUtils.errLog("Config is empty") end ScmsUtils.boldlog("Built website:") ScmsUtils.log(ScmsUtils.uriEncode("file:///#{website}")) end def Scms.generatePages(website, settings, options) # build pages defined in config file Scms.generatePagesFromSettings(website, settings, options) # build pages pased on _pages folder Scms.generatePagesFromFolder(website, settings, options) end def Scms.generatePagesFromSettings(website, settings, options) if settings["pages"] != nil ScmsUtils.log("Compiling Pages:") settings["pages"].each do |pagedata| if pagedata != nil pagedata.each do |pageOptions| pagename = pageOptions[0] pageconfig = pageOptions[1] pageOptions = PageOptions.new(pagename, website, pageconfig, settings) views = Scms.getSettingsViews(pageconfig["views"], website, pageOptions, options) # Dont save a page if no views have been defined (so the config han have pages for nav building) break if views.length < 1 Scms.savePage(settings, website, pageOptions, views, options) end end end end end def Scms.getSettingsViews(settingsViews, website, pageOptions, options) views = Hash.new {} if settingsViews != nil settingsViews.each do |view| viewname = view[0] viewparts = view[1].split("?") # This allows views to have a query string in the config viewpath = viewparts[0] viewqs = viewparts[1] viewData = Hash[viewqs.split('&').map{ |q| q.split('=') }] if viewqs != nil viewmodel = Scms.getViewModel(viewname, viewpath, website, pageOptions, options, viewData) views[viewname] = Scms.renderView(viewpath, viewmodel) end end return views end def Scms.generatePagesFromFolder(website, settings, options) pagesFolder = File.join(website, "_pages") Dir.glob("#{pagesFolder}/**/*/").each do |pageFolder| pagename = File.basename(pageFolder, ".*") pageconfig = nil pageconfig = Scms.getSettings(pageFolder) if File.exists?(File.join(pageFolder, "_config.yml")) pageOptions = PageOptions.new(pagename, website, pageconfig, settings) views = Hash.new {} if pageconfig != nil views = Scms.getSettingsViews(pageconfig["views"], website, pageOptions, options) if pageconfig["views"] != nil end Dir.glob(File.join(pageFolder, "*")).reject { |f| f =~ /\.yml$/ || File.directory?(f) }.each do |view| viewname = File.basename(view, ".*") viewpath = Pathname.new(view).relative_path_from(Pathname.new(website)).to_s viewmodel = Scms.getViewModel(viewname, viewpath, website, pageOptions, options) views[viewname] = Scms.renderView(viewpath, viewmodel) end Scms.savePage(settings, website, pageOptions, views, options) end end def Scms.getViewModel(viewname, viewpath, website, pageOptions, options, viewData = nil) #puts "parsing view: #{viewname}" viewmodel = Hash.new {} viewfullpath = File.join(website, viewpath) if File.exists?(viewfullpath) viewmodel = { :name => pageOptions.name, :title => pageOptions.title, :url => pageOptions.url, :resource => pageOptions.resource, :rootdir => website, :mode => options[:mode], :allowEdit => pageOptions.allowEdit, :view => { :name => viewname, :path => viewpath, :data => viewData } } else ScmsUtils.errLog("View not found: #{viewname} [#{viewpath}]") ScmsUtils.writelog("::View not found: #{viewname} [#{viewpath}]", website) ScmsUtils.writelog("type NUL > #{viewpath}", website) end return viewmodel end def Scms.renderView(viewpath, hash = Hash.new) #puts "** Rendering: #{viewpath} **" htmlsnipet = "" begin htmlsnipet = File.read(viewpath) rescue Exception=>e ScmsUtils.errLog(e.message) ScmsUtils.log(e.backtrace.inspect) end ScmsUtils.log("Empty view: #{viewpath}") if htmlsnipet.empty? template = "" case File.extname(viewpath) when ".xml" template = ScmsXmlHandler.transform(htmlsnipet) when ".md" begin htmlsnipet = htmlsnipet.encode('UTF-8', :invalid => :replace, :undef => :replace) doc = Maruku.new(htmlsnipet) template = doc.to_html rescue Exception => e template = htmlsnipet ScmsUtils.errLog(e.message) ScmsUtils.log(e.backtrace.inspect) end else template = htmlsnipet end parser = ScmsParser.new(template, hash) return parser.parse(viewpath) end def Scms.savePage(settings, website, pageOptions, views, options) fileName = File.join(website, File.join(pageOptions.url.sub('~/',''))) erb = File.join(website, pageOptions.template) #ScmsUtils.log("Generating: #{fileName} with #{pageOptions.template}") if File.exists?(erb) bundleModel = Scms.getBundleModel(website, settings, options)# Build bundle model navModel = Scms.getNavModel(website, settings, options)# Build navigation model websiteroot = '/' websiteroot = settings["rooturl"] if settings["rooturl"] != nil websiteroot = ScmsUtils.uriEncode("file:///#{website}/") if options[:mode] == "cms" monkeyhook = ""; monkeyhook = "".gsub("~/", websiteroot) if options[:mode] == "cms" livereload = "" if options[:watch] livereload = "" if options[:mode] != "cms" end pagemodel = Hash.new {} pagemodel = { :name => pageOptions.name, :title => pageOptions.title, :description => pageOptions.description, :keywords => pageOptions.keywords, :url => pageOptions.url, :resource => pageOptions.resource, :bundles => bundleModel, :navigation => navModel, :views => views, :rootdir => website, :monkeyhook => monkeyhook, :livereload => livereload } pubsubdir = File.dirname(fileName) Dir.mkdir(pubsubdir, 755) unless File::directory?(pubsubdir) erbtemplate = File.read(erb) parser = ScmsParser.new(erbtemplate, pagemodel) html = parser.parse() html = html.gsub('~/', websiteroot) begin File.open(fileName, 'w') {|f| f.write(html) } ScmsUtils.successLog("Generated: #{pageOptions.url}") rescue Exception=>e ScmsUtils.errLog(e.message) ScmsUtils.log(e.backtrace.inspect) end else ScmsUtils.errLog("Template doesn't exist: #{pageOptions.template}") ScmsUtils.writelog("::Template doesn't exist #{pageOptions.template}", website) ScmsUtils.writelog("type NUL > #{erb}", website) end end def Scms.getNavModel(website, settings, options) websiteroot = '/' websiteroot = settings["rooturl"] unless settings["rooturl"] == nil websiteroot = ScmsUtils.uriEncode("file:///#{website}/") if options[:mode] == "cms" #websiteroot = "" if options[:mode] == "cms" navModel = Array.new if settings["pages"] != nil settings["pages"].each do |pagedata| if pagedata != nil pagedata.each do |pageoptions| pagename = pageoptions[0] pageconfig = pageoptions[1] pageurl = "about:blank" pageurl = pageconfig["generate"] pageurl = pageconfig["url"] unless pageconfig["url"] == nil navtext = pageconfig["navigation"] navmeta = pageconfig["navigation_meta"] navModel.push({"text" => navtext, "url" => pageurl.gsub("~/", websiteroot), "pagename" => pagename, "meta" => navmeta}) unless navtext == nil end end end end if settings["nav"] != nil settings["nav"].each do |pagedata| if pagedata != nil pagedata.each do |pageoptions| pagename = pageoptions[0] pageconfig = pageoptions[1] pageurl = "about:blank" pageurl = pageconfig["url"] unless pageconfig["url"] == nil #pageUrlExt = File.extname(pageurl) #puts "pageUrlExt: #{pageUrlExt}" #puts "No extension" if pageUrlExt == "" if options[:mode] == "cms" pageurl += "index.html" if pageurl.match(/\/$/) end navtext = pagename navtext = pageconfig["text"] navmeta = pageconfig["meta"] navModel.push({"text" => navtext, "url" => pageurl.gsub("~/", websiteroot), "pagename" => pagename, "meta" => navmeta}) end end end end return navModel end def Scms.getBundleModel(website, settings, options) bundleModel = Hash.new {} websiteroot = '/' websiteroot = settings["rooturl"] unless settings["rooturl"] == nil websiteroot = ScmsUtils.uriEncode("file:///#{website}/") if options[:mode] == "cms" Dir.glob('**/*.bundle').each do|bundle| getGeneratedBundleName = ScmsBundler.getGeneratedBundleName(bundle) stub = ScmsBundler.toStub(bundle) bundleModel[bundle] = getGeneratedBundleName bundleModel[stub] = getGeneratedBundleName #Access bundle model without bundle extention end bundleConfig = settings["bundles"] if bundleConfig != nil bundleConfig.each do |bundle| #ScmsUtils.log( "bundle (#{bundle.class}) = #{bundle}" ) bundle.each do |option| name = option[0] config = option[1] bundleName = File.join(config["generate"]) bundleModel[name] = bundleName.gsub("~/", websiteroot) end end end # puts "Bundle model:" # puts bundleModel # puts "----------------------------" return bundleModel end def Scms.bundler(bundle = nil) if bundle == nil ScmsBundler.run() else ScmsBundler.bundle(bundle) end end def Scms.bundle(settings, website) Scms.bundler() bundleConfig = settings["bundles"] if bundleConfig != nil ScmsUtils.boldlog("Bundeling:") bundleConfig.each do |bundle| #ScmsUtils.log( "bundle (#{bundle.class}) = #{bundle}" ) bundle.each do |option| name = option[0] config = option[1] bundleName = File.join(config["generate"].gsub("~/","")) content = "" assetList = "" files = config["files"] if files != nil files.each do |asset| assetList += " - #{asset}\n" assetdir = File.join(website, asset) if File::exists?(assetdir) #try catch for permisions begin content = content + "\n\n" + File.read(assetdir) rescue Exception=>e ScmsUtils.errLog(e.message) ScmsUtils.log(e.backtrace.inspect) ScmsUtils.log("#{assetList}") end else ScmsUtils.errLog("Asset file doesn't exists: #{asset}") ScmsUtils.writelog("::Asset file doesn't exists: #{asset}", website) ScmsUtils.writelog("type NUL > #{assetdir}", website) end end else ScmsUtils.errLog("No files in bundle"); end bundleFullPath = File.join(website, bundleName) bundleDir = File.dirname(File.join(website, bundleName)) begin Dir.mkdir(bundleDir, 755) unless File::directory?(bundleDir) File.open(bundleFullPath, 'w') {|f| f.write(content) } ScmsUtils.successLog("Created: #{bundleName}") rescue Exception=>e ScmsUtils.errLog("Error creating bundle: #{bundleName}") ScmsUtils.errLog(e.message) ScmsUtils.log(e.backtrace.inspect) end if File.extname(bundleName) == ".js" #puts "Minifing: #{bundleName}" Scms.packr(bundleFullPath) unless /(-min)|(\.min)/.match(bundleName) end end end end end def Scms.sassall(website) ScmsUtils.log("Minimising Sass Files (.scss)") Dir.chdir(website) do Dir.glob("**/*.{scss}").each do |asset| Scms.sass(asset) end end end def Scms.sass(asset) if File.exists?(asset) begin template = File.read(asset) sass_engine = Sass::Engine.new(template, { :style => :compressed, :cache => false, :syntax => :scss }.freeze) output = sass_engine.to_css css_file = "#{File.dirname(asset)}/#{File.basename(asset,'.*')}.css" File.open(css_file, 'w') { |file| file.write(output) } ScmsUtils.log( "CSS minified (sassed): #{css_file}" ) rescue Exception => e ScmsUtils.errLog("Error processing: #{asset}") ScmsUtils.errLog(e.message) end else ScmsUtils.errLog("Sass file doesn't exists: #{asset}") end end def Scms.packr(asset) #puts "Trying to pack: #{asset}" if File.exists?(asset) begin code = File.read(asset) compressed = Packr.pack(code) File.open(asset, 'w') { |f| f.write(compressed) } ScmsUtils.log("Minified #{File.basename(asset)}") rescue Exception => e ScmsUtils.errLog("Error processing: #{asset}") ScmsUtils.errLog(e.message) end else ScmsUtils.errLog("Can't minify asset because file doesn't exist: #{asset}") end end def Scms.copyWebsite(website, pub) if pub.to_s.strip.length != 0 FileUtils.mkdir pub unless Dir.exists? pub source = File.join(website) Dir.chdir(source) do Dir.glob("**/*").reject{|f| f['.svn']}.each do |oldfile| newfile = File.join(pub, oldfile.sub(source, '')) #puts newfile File.file?(oldfile) ? FileUtils.copy(oldfile, newfile) : FileUtils.mkdir(newfile) unless File.exist? newfile end end ScmsUtils.log("Output to: #{ScmsUtils.uriEncode("file:///#{pub}")}") end end end