Skip to content

Commit

Permalink
Setup HTML parsing and local server
Browse files Browse the repository at this point in the history
  • Loading branch information
denysdovhan committed Mar 7, 2017
1 parent 48b92ac commit 268aa9d
Show file tree
Hide file tree
Showing 7 changed files with 1,012 additions and 52 deletions.
3 changes: 3 additions & 0 deletions exercises/hello_world/solution/en.md
@@ -0,0 +1,3 @@
# Neat!

You've solved this problem!
4 changes: 4 additions & 0 deletions package.json
Expand Up @@ -31,8 +31,12 @@
"node": ">=4.0.0"
},
"dependencies": {
"chokidar": "^1.6.1",
"colors": "^1.1.2",
"diff": "^3.2.0",
"express": "^4.15.2",
"fast-html-parser": "^1.0.1",
"openurl": "^1.1.1",
"workshopper-adventure": "^6.0.1"
},
"devDependencies": {
Expand Down
16 changes: 0 additions & 16 deletions utils/fail.js

This file was deleted.

10 changes: 10 additions & 0 deletions utils/parse.js
@@ -0,0 +1,10 @@
const fs = require('fs');
const HTMLParser = require('fast-html-parser');

module.exports = filename => new Promise((resolve, reject) => {
fs.readFile(filename, 'utf8', (err, content) => {
if (err) return reject(err);
const tree = HTMLParser.parse(content);
return resolve(tree.firstChild.structure);
});
});
71 changes: 60 additions & 11 deletions utils/problem.js
@@ -1,41 +1,90 @@
const fs = require('fs');
const path = require('path');
const remark = require('remark');
const html = require('remark-html');
const express = require('express');
const chokidar = require('chokidar');
const express = require('express');
const open = require('openurl').open;
const equal = require('deep-equal');

const fail = require('./fail');
const parse = require('./parse');
const troubleshooting = require('./troubleshooting');

module.exports = (dirname) => {
const exports = {};

exports.init = function init(workshopper) {
// Get lang code
const lang = workshopper.i18n.lang();

this.problem =
{ file: path.join(dirname, `${lang}.md`) };
this.solutionPath =
path.resolve(dirname, 'solution', 'solution.html');
this.solution = [
{ text: fs.readFileSync(this.solutionPath), type: 'plain' },
{ text: fs.readFileSync(this.solutionPath), type: 'html' },
{ file: path.join(dirname, 'solution', `${lang}.md`) },
];
this.troubleshooting =
path.join(__dirname, '..', 'i18n', 'troubleshooting', `${lang}.md`);
};

exports.verify = function verify(args, done) {
// do verifying
return done(true); // everything is OK
// return done(false); // something wen't wrong
Promise.all([parse(args[0]), parse(this.solutionPath)])
.then(([attempt, solution]) => {
if (attempt === solution) {
return done(true);
}

exports.fail = troubleshooting({
troubleshooting: this.troubleshooting,
filename: args[0],
attempt,
solution,
});

return done(false);
})
.catch((reason) => {
console.error(reason);
done(false);
});
};

exports.run = function run(args, done) {
// run the file
const filename = args[0];
let result = '';

const watcher = chokidar.watch(filename);
const server = express();

watcher.on('add', (file) => {
console.log(`${file} has been added.`);
result = fs.readFileSync(filename, 'utf8');
});

watcher.on('change', (file) => {
console.log(`${file} has been changed.`);
result = fs.readFileSync(filename, 'utf8');
});

watcher.on('unlink', (file) => {
console.warn(`${file} has been unlinked.`);
done();
});

watcher.on('error', (file) => {
console.error(`${file} has been errored.`);
done();
});

server.get('*', (req, res) => {
res.send(result.toString());
});

server.listen(process.env.HOST || 3000, () => {
console.log(`
File is served on http://localhost:3000/
Hit Ctrl+C to exit.
`);
open('http://localhost:3000/');
});
};

return exports;
Expand Down
50 changes: 38 additions & 12 deletions utils/troubleshooting.js
@@ -1,16 +1,42 @@
const fs = require('fs');
const path = require('path');
const diff = require('./diff');

module.exports = function troubleshooting(path, data) {
return fs.readFileSync(path, 'utf8')
// Replace breaking characters
.replace(/'/g, "'")
.replace(/"/g, '"')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
// Inject data
.replace(/%solution%/g, data.solution)
.replace(/%attempt%/g, data.attempt)
.replace(/%diff%/g, diff(data.attempt, data.solution))
.replace(/%filename%/, data.filename);
/**
* Format troubleshooting message
* This function reads the troubleshooting file and replaces kewords
* by data providen in `data` object
*
* @param {String} file Path to troubleshooting file:
* @see ../i18n/troubleshooting/
* @param {Object} data Object with corresponding data
* @return {String}
*/
const format = (file, data) => fs.readFileSync(file, 'utf8')
// Replace breaking characters
.replace(/&#39;/g, "'")
.replace(/&quot;/g, '"')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
// Inject data
.replace(/%solution%/g, data.solution)
.replace(/%attempt%/g, data.attempt)
.replace(/%diff%/g, diff(data.attempt, data.solution))
.replace(/%filename%/, data.filename);

/**
* Compose fail message
* @param {Object} data Object with data that's needed for formating
* @return {Array}
*/
module.exports = function troubleshooting(data) {
return [{
text: format(data.file, data),
type: 'md',
}, {
text: '---',
type: 'md',
}, {
file: path.join(__dirname, '..', 'i18n', 'footer', '{lang}.md'),
}];
};

0 comments on commit 268aa9d

Please sign in to comment.