109 lines
3.3 KiB
JavaScript
109 lines
3.3 KiB
JavaScript
|
|
// This plugin to Meteor uses the linter plugin api to package up all the templates indexed by name into a single file saved in the /private folder in the project.
|
|
// The file is intended to be used to service search engine requests for static html by utilizing server side rendering of the templates.
|
|
// Meteor packages up all the content not in /private or /public, so simply accessing the templates at runtime on the server does not appear to be an option.
|
|
|
|
const fs = Npm.require('fs');
|
|
const path = Npm.require('path');
|
|
|
|
//Disabled linter for now. Supposedly Google at least can manage SEO without server side rendering.
|
|
//Plugin.registerLinter({
|
|
// extensions: ["html"]
|
|
// //filenames: [".jshintrc"]
|
|
//}, () => new S3);
|
|
|
|
|
|
class S3 {
|
|
constructor() {
|
|
this.templateStart = /<template\s+name\s*=\s*(['"])\b(.*?)\1\s*>/;
|
|
this.templateEnd = /<\/\s*template\s*>\s*/;
|
|
}
|
|
extractTemplate(html, map) {
|
|
try {
|
|
let result = html.match(this.templateStart);
|
|
|
|
if(result != null) {
|
|
let name = result[2];
|
|
|
|
html = html.substring(result.index + result[0].length);
|
|
result = html.match(this.templateEnd);
|
|
//console.log("Matching: \n" + html);
|
|
//console.log("\n" + result);
|
|
|
|
if(result != null) {
|
|
let contents = html.substring(0, result.index);
|
|
html = html.substring(result.index + result[0].length);
|
|
|
|
//Save the template contents indexed by its name.
|
|
//TODO: Warn if we overwrite any template names??? Should never happen unless the developer made an error in naming.
|
|
map[name] = contents;
|
|
//console.log("Found template: " + name);
|
|
//console.log(contents);
|
|
}
|
|
else html = null;
|
|
}
|
|
else html = null;
|
|
} catch(err) {
|
|
console.log(err);
|
|
html = null;
|
|
}
|
|
|
|
return html;
|
|
}
|
|
processFilesForPackage(files, options) {
|
|
try {
|
|
let map = {};
|
|
//let fileNames = [];
|
|
let _this = this;
|
|
let originalContents = fs.readFileSync('private/template-index', {encoding: 'utf8', flag: 'r'});
|
|
let counter = 0;
|
|
|
|
//Extract all templates for every file processed (all HTML files).
|
|
files.forEach((file) => {
|
|
if(file._source.relPath.startsWith("imports/")) { /// && file._source.relPath === "imports/ui/Test.html"
|
|
let html = file.getContentsAsString();
|
|
|
|
while(html != null) {
|
|
//Will return null if no more templates are to be found.
|
|
html = this.extractTemplate(html, map);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
//Returns a 16 character hex hash that is zero padded.
|
|
let hashString = (str)=> {
|
|
let hash = 0;
|
|
|
|
if(str.length === 0) return hash;
|
|
|
|
for(let i = 0; i < str.length; i++) {
|
|
let chr = str.charCodeAt(i);
|
|
hash = ((hash << 5) - hash) + chr;
|
|
hash |= 0; // Convert to 32bit integer
|
|
}
|
|
|
|
return ("0000000000000000" + hash.toString(16)).substr(-16);
|
|
};
|
|
|
|
let output = JSON.stringify(map);
|
|
//console.log("Out: " + output);
|
|
let hash = hashString(output);
|
|
//console.log("Hash: " + hash);
|
|
let originalHash = hashString(originalContents);
|
|
|
|
//console.log(originalHash);
|
|
|
|
if(originalHash !== hash) {
|
|
//console.log("Hash does not match!");
|
|
//Write the mapping to a 'template-index' file in the private folder.
|
|
fs.writeFile('private/template-index', output);
|
|
}
|
|
else {
|
|
//console.log("Hash matches..");
|
|
}
|
|
} catch(err) {
|
|
console.log(err);
|
|
}
|
|
}
|
|
} |