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