Page.js 6.33 KB
//this is basic class for loading page/layout data from json or csv files

module.exports = function(params) {
 require('require-csv')//lightweight class for parsing possible csv data
 var fs = require("fs"),
	 engine = params["engine"]



 var $type = params["type"] || "page" //page or layout?
 var $name = params["name"] //page or layout name
 var $main_template = null
 var $partials = {} //will hold all compiled partials that will be passed onto the base Mustache template for further processing
 var $vars = {} //holds the variables and data that will be accessed in mustache via page.variableName or layout.variableName

 var $data_dir = ''
 var $views_dir = ''

 this.initiate = function(callback) {//reading and initiate page data from json file
    $data_dir = params.path['data'];
	var filename = $data_dir +"/"+$type+"s/"+ $name + '.json';
	var data = fs.readFileSync(filename, 'utf-8')
	$vars = JSON.parse(data);
	
	if('alias' in $vars) {
		$name = $vars['alias'];
		filename = $data_dir +"/"+$type+"s/"+ $name + '.json';
		data = fs.readFileSync(filename, 'utf-8')
		$vars = extend(JSON.parse(data), $vars)
	}

	
	if($type != "layout" && !("layout" in $vars)) $vars["layout"] = "default";

	map_script_names();
	//now load all data relating to this page
	load_data($data_dir)

	var wait_for_compression = false;

	//load inline scripts and styles
	$views_dir = params.path['views'];
	if($type == 'page') {
		if(fs.existsSync($views_dir + '/assets/scripts/' + $name + '.js')) {
			if(params.compressor) {
				wait_for_compression = true;
				params.compressor.compress($views_dir + '/assets/scripts/' + $name + '.js', {
					charset: 'utf8',
					type: 'js'
				}, function(err, data, extra) {
					if(err) console.log(err);
					$vars['inline_scripts'] = data;
					callback.call();
				});
			} 
			else $vars['inline_scripts'] = fs.readFileSync($views_dir + '/assets/scripts/' + $name + '.js' , 'utf-8');
		}
		if(fs.existsSync($views_dir + '/assets/styles/' + $name + '.css')) {
			$vars['inline_styles'] = fs.readFileSync($views_dir + '/assets/styles/' + $name + '.css' , 'utf-8')
		}
	}

	if( !wait_for_compression && typeof callback === "function" ) callback.call();

 }


 /**
  This functions loads the data related to each page or layout
  for a page we load all files in the related directory
  for a layout we check the "datas-sources" attribute of our layout_file.json and load them
  In your real world application you can load data only when it is needed according to each page inside controllers
 */
 var load_data = function(data_dir) {
	var data_files = {}

	var format = new RegExp("([0-9a-z\\-_]+)\\.(json|csv)$" , "i");

	//see if there's a folder for partial data relating to this page or layout
	//if so iterate all json/csv files and load the data
	var partial_data_folder = data_dir + "/"+$type +"s/partials/" + $name;
	var stats;
	if(fs.existsSync(partial_data_folder) && (stats = fs.statSync(partial_data_folder)) && stats.isDirectory()) {
		var files = fs.readdirSync(partial_data_folder)
		files.forEach(function (name) {
			var filename;//file name, which we use as the variable name
			if (! (filename = name.match(format)) ) return;
			data_files[filename[1]] = partial_data_folder + "/" + name;
		})
	}


	for(var var_name in data_files) if(data_files.hasOwnProperty(var_name)) {

		var new_data
		try {
			if(data_files[var_name].match(/\.json$/i)) {
				new_data = fs.readFileSync(data_files[var_name] , 'utf-8');
				new_data = JSON.parse(new_data);
			} else if(data_files[var_name].match(/\.csv$/i)) {
				//load csv data into an array
				var csv_data = require(data_files[var_name]);
				
				//now convert it to json
				var csv_header = csv_data[0];
				var length = csv_data.length;

				var json_data = []
				for(var i = 1 ; i < length; i++) {
					var csv_row = csv_data[i];
					var json_row = {}
					for(var j = 0; j < csv_row.length; j++) {
						json_row[csv_header[j]] = csv_row[j];
					}
					//for example if we have "status":"pending" , add this to it as well : "pending":true
					if("status" in json_row) json_row[json_row["status"].toLowerCase()] = true;
					json_data.push(json_row);
				}
				
				new_data = json_data
			}
		} catch(e) {
			console.log("Invalid JSON Data File : " + data_files[var_name]);
			continue;
		}
		
		$vars[var_name.replace(/\./g , '_')] = new_data
		//here we replace '.' with '_' in variable names, so template compiler can recognize it as a variable not an object
		//for example change sidebar.navList to sidebar_navList , because sidebar is not an object

	}


  return true;
 }


 //in our page's data file, we save short script/style names, which we must map to original file names
 //this way we can easily only change the script-mapping file and changes will be reflected
 var map_script_names = function() {
	var mappables = ["script" , "style"]
	for(var m in mappables) {
	  var which = mappables[m]
	  if($vars[which+'s']) {//if we have $vars["scripts"] or $vars["styles"]
		var page_scripts = $vars[which+'s'];
		var map_json = JSON.parse(fs.readFileSync($data_dir + "/common/"+which+"-mapping"+(params.path['minified'] ? '.min' : '')+".json"));
		var mapped_scripts = [];
		for(var i in page_scripts) {
			if(page_scripts[i] in map_json) {
				if(typeof map_json[page_scripts[i]] == "string") mapped_scripts.push(map_json[page_scripts[i]])
				else if(typeof map_json[page_scripts[i]] == "object") //two or more scripts should be included for this to work, like dataTables, jQuery UI, etc ...
				{
					for(var m in map_json[page_scripts[i]])
						mapped_scripts.push(map_json[page_scripts[i]][m])
				}
			}
		}
		$vars[which+'s'] = mapped_scripts;

		if(('ie_'+which+'s') in $vars) {
			var ie_scripts = $vars['ie_'+which+'s'];//ie_scripts || ie_styles
			var ie_mapped_scripts = [];
			for(var i in ie_scripts) if(map_json[ie_scripts[i].name])
			{
				ie_mapped_scripts.push({"version" : ie_scripts[i].version , "file_name" : map_json[ie_scripts[i].name]})
			}

			$vars['ie_'+which+'s'] = ie_mapped_scripts
		}
	  }
	}
 }
 






 this.get_template = function() {
	var template_file = $views_dir+"/"+$type+"s/"+$name + '.mustache';
	if(fs.existsSync(template_file)) {
		return params.engine.compile(fs.readFileSync(template_file , 'utf-8'));
	} 
	return null;
 }
 this.get_vars = function() {
	return $vars;
 }
 this.get_var = function(name , undefined) {
	return name in $vars ? $vars[name] : undefined;
 }
 this.get_name= function() {
	return $name;
 }

 
}