Updated to nearly fully functional. Pre-release 1. Still needs some UI changes in the slideshow and admin pages (move the save button & fix the save detection for the internship list). Customer had one more page change request which I need to re-define and handle.
This commit is contained in:
109
packages/server-side-seo/build.js
Normal file
109
packages/server-side-seo/build.js
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
packages/server-side-seo/package.js
Normal file
17
packages/server-side-seo/package.js
Normal file
@@ -0,0 +1,17 @@
|
||||
Package.describe({
|
||||
name: "wcrisman:server-side-seo",
|
||||
version: "1.0.0",
|
||||
summary: "Copies all templates into an index file: /private/template-index for use at runtime to generate html for search engines to parse.",
|
||||
documentation: "readme.md"
|
||||
});
|
||||
|
||||
Package.registerBuildPlugin({
|
||||
name: "wcrisman:server-side-seo-build",
|
||||
sources: ["build.js"],
|
||||
//npmDependencies: {'something-from-npm': '1.2.3'}
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
//api.use('');
|
||||
api.use('isobuild:linter-plugin@1.0.0');
|
||||
});
|
||||
Reference in New Issue
Block a user