//Implement SEO (title and description) to Challenge Listing and update Challenge Details following requirements below.
//Make sure to react-helmet renders on the server side, test your solution looking for source code in the web browser and check if Title and Description Meta are updated as expected.var counter = 0;// check sure asyncLoad get's called first by forcing assignment
module.exports.asyncLoad = function (html_content, files_in_directory, files) {
return new Promise(function (resolve, reject) { setTimeout(function () {counter = 1;resolve();}, 100);});}
module.exports.test = function (query_selector) {counter++;el = query_selector('#test');el.innerHTML = counter;}d3 = require('d3')
module.exports.test = function (query_selector) {var circle = d3.select(this.document).select('#test')
.append('svg:svg')
.attr('width', 600)
.attr('height', 300)
.append('circle')
.attr('cx', 300)
.attr('cy', 150)
.attr('r', 10)
.attr('fill', '#26963c');}
const jsdom = require('jsdom');const requireFromString = require('require-from-string');
const path = require('path');const debug = require('debug')('metalsmith-preprocess');module.exports = function (options) {const defaults = {
preprocess: 'preprocess.js', // contains js code to run on server
collection: 'content',
asyncLoad: 'asyncLoad',}options = options || {};Object.keys(defaults).forEach((defaultOption) => {
if (!options.hasOwnProperty(defaultOption))
options[defaultOption] = defaults[defaultOption];});function preprocess (htmlFile, preprocess, filesInDirectory, files) {
debug('runPreprocess', htmlFile.directory, preprocess);
preprocess = requireFromString(preprocess.contents.toString(),
path.join('src', preprocess.directory, preprocess.filename));// split renders and asyncLoad
var loaded = preprocess.hasOwnProperty(options.asyncLoad) ?
preprocess[options.asyncLoad](htmlFile, filesInDirectory, files) :
Promise.resolve();return loaded.then((result) => {debug('then', htmlFile.directory);
return new Promise((resolve, reject) => {jsdom.env({
features: { QuerySelector: true },html: htmlFile.contents.toString(),
done: (errors, window) => {if (errors)reject(errors);Object.keys(preprocess)
.filter((key) => { return key !== options.asyncLoad; })
.forEach((key) => {const renderer = preprocess[key];
renderer.call(window, window.document.querySelector.bind(window.document));});htmlFile.contents = Buffer.from(window.document.documentElement.innerHTML, 'utf-8');
debug('resolving', htmlFile.directory);resolve();}});});});}return (files, metalsmith, done) => {const promises = [];const re_filename = /^(\S+)\/(\S+)$/;
debug('metalsmith-preprocess', Object.keys(files).length);// update or add directory and filename for each file
Object.keys(files).forEach((file) => {const match = re_filename.exec(file);
if (match === null) {files[file].directory = "";files[file].filename = file;return;}
files[file].directory = match[1];files[file].filename = match[2];});const contentFilenames = Object.keys(files)
// filter filepath list to content files only
.filter((file) => {return new Set(files[file].collection).has(options.collection);});
const collections = metalsmith.metadata().collections;// test for collection
if (collections === undefined || !collections.hasOwnProperty(options.collection)) {
done(Error("Collection, " +options.collection +", Not Found. Check your metalsmith build."));}// create a map of content filenames to other filenames in the same directory
const contentDirectories = new Map(contentFilenames.map((file) => {
const filesInDirectory = new Set(Object.keys(files).filter((f) => {
return file.directory === f.directory; }));return [file, filesInDirectory];}));// run preprocess functions for preprocess files found in content directories
contentDirectories.forEach((filesInDirectory, file) => {
const contentFile = files[file];const preprocessFilename = path.join(contentFile.directory, options.preprocess);
if (!filesInDirectory.has(preprocessFilename)) return;
debug('expecting', preprocessFilename, "with", filesInDirectory);
promises.push(preprocess(contentFile, files[preprocessFilename], filesInDirectory, files));});// why doesn't then just accept done as an argument?
debug('Checking promises:', promises);
Promise.all(promises)
.then((result) => { done(); })
.catch((error) => { done(error); });}}var assert = require('assert');var cheerio = require('cheerio');
var collections = require('metalsmith-collections');
var preprocess = require('..');var Metalsmith = require('metalsmith');describe('Initialization', () => {
it('should complain if collection has not been set', (done) => {
var metalsmith = Metalsmith('test/fixtures/basic');
metalsmith
.use(preprocess())
.build((err, files) => {assert.ok(err, "is an error");
assert.ok(err.message.includes('Collection'), "is collection error");done();});});it('should not complain if collection has no files', (done) => {
var metalsmith = Metalsmith('test/fixtures/basic');
metalsmith
.use(collections({content: {pattern: 'nada.html',}}))
.use(preprocess())
.build((err, files) => {assert.ok(files, "has files");done();});});it('should complain if preprocess collection id not found', (done) => {
var metalsmith = Metalsmith('test/fixtures/basic');
metalsmith
.use(collections({randomName: {pattern: 'index.html',}}))
.use(preprocess())
.build((err, files) => {assert.ok(err, "is an error");
assert.ok(err.message.includes('Collection'), "is collection error");done();});});it('should load user specified collections', (done) => {
var metalsmith = Metalsmith('test/fixtures/basic1');
metalsmith
.use(collections({randomName: {pattern: 'index.html',}}))
.use(preprocess({collection: 'randomName'}))
.build((err, files) => {if (err) return done(err);
$ = cheerio.load(files['index.html'].contents.toString());
assert.equal($('#test').text(), '2')
done();});});it('should work with specified asyncLoad option and preprocess option', (done) => {
var metalsmith = Metalsmith('test/fixtures/options');
metalsmith
.use(collections({content: {pattern: 'index.html',}}))
.use(preprocess({ asyncLoad: 'testAsyncLoad',preprocess: 'testPreprocess.js' }))
.build((err, files) => {if (err) return done(err);
$ = cheerio.load(files['index.html'].contents.toString());
assert.equal($('#test').text(), '2')
done();});});});describe('Rendering', () => {
it('should call preprocess.asyncLoad and other exported preprocess', (done) => {
var metalsmith = Metalsmith('test/fixtures/basic1');
metalsmith
.use(collections({content: {pattern: 'index.html',}}))
.use(preprocess())
.build((err, files) => {if (err) return done(err);
$ = cheerio.load(files['index.html'].contents.toString());
assert.equal($('#test').text(), '2')
done();});});it('should render d3', (done) => {var metalsmith = Metalsmith('test/fixtures/d3');
//needs to use collections, but why doesn't the error perculate up?
metalsmith
.use(collections({content: {pattern: 'index.html',}}))
.use(preprocess())
.build((err, files) => {if (err) return done(err);
$ = cheerio.load(files['index.html'].contents.toString());// svg should be in there
assert.ok($('#test').html().includes("circle"), "#test contains circle");done();});});});
//by splay emu, updated by me, question of how to get the server to sign user without auth to make profile.
YOU ARE READING
My Prog Adventures
SpiritualI am also a programmer. I have been intending to post some of my scripts on here. I can teach math and programming, please reach out to me in conversations, my messages on here isnt working.