diff --git a/comment/Makefile b/comment/Makefile deleted file mode 100644 index eceaff4..0000000 --- a/comment/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -JSHINT = node_modules/.bin/jshint -BROWSERIFY = node_modules/.bin/browserify -CASPERJS = node_modules/.bin/casperjs -EXORCIST = node_modules/.bin/exorcist -CASPERJS = ./node_modules/.bin/casperjs --ssl-protocol=tlsv1 - -BUNDLE = ../public/comment.js -MAP = $(BUNDLE).map - -export SHELLOPTS:=errexit:pipefail - -.DELETE_ON_ERROR: - -all: $(BUNDLE) - -$(BUNDLE): comment.js Makefile - rm -f $(MAP) - $(BROWSERIFY) --standalone bcComment --debug -t brfs -t uglifyify $< | $(EXORCIST) $(MAP) > $@ - -test: - $(CASPERJS) test tests/stories/validation.js - -.PHONY: all diff --git a/comment/README.md b/comment/README.md deleted file mode 100644 index 00de5dd..0000000 --- a/comment/README.md +++ /dev/null @@ -1,21 +0,0 @@ -Comment form subproject. - -## Building - -Install dependencies (in comment directory): - - npm install - -Build bundle: - - make all - -## Testing - -Load Blog-Core tests (in main project root): - - swipl -s tests/tests.pl - -Run frontend tests (in comment directory): - - make test diff --git a/comment/comment.js b/comment/comment.js deleted file mode 100644 index 5e3265c..0000000 --- a/comment/comment.js +++ /dev/null @@ -1,424 +0,0 @@ -// Trim shim for IE8. - -if (typeof String.prototype.trim !== 'function') { - - String.prototype.trim = function() { - - return this.replace(/^\s+|\s+$/g, ''); - }; -} - -// Helper for API queries. - -var api = { - - // Retrieves captcha question. - - question: function(cb) { - - var xhr = new XMLHttpRequest(); - - xhr.open('GET', '/api/question', true); - - xhr.onreadystatechange = api.ready(xhr, cb); - - xhr.send(); - }, - - // Sends new comment. - - post: function(id, values, cb) { - - var xhr = new XMLHttpRequest(); - - var url = '/api/post/' + encodeURIComponent(id) + '/comment'; - - xhr.open('POST', url, true); - - xhr.setRequestHeader('Content-Type', 'application/json'); - - xhr.onreadystatechange = api.ready(xhr, cb); - - xhr.send(JSON.stringify(data)); - }, - - // Returns function for state change. - - ready: function(xhr, cb) { - - return function() { - - if (xhr.readyState === 4) { - - if (xhr.status === 200) { - - cb(null, JSON.parse(xhr.responseText)); - - } else { - - cb(new Error('API error.')); - } - } - } - } -}; - -// Helper to extract values from input elements. - -var input = { - - string: function(element) { - - return element ? element.value.trim() : undefined; - }, - - check: function(element) { - - return element ? element.checked : false; - }, - - int: function(element) { - - return element ? parseInt(element.value, 10) : undefined; - } -}; - -// Helpers to validate data. - -var validator = { - - // String validators. - - string: { - - is_set: function(value, list) { - - if (typeof value === 'undefined' || - value.length === 0) { - - list.push('__ must be set.'); - } - }, - - email: function(value, list) { - - if (typeof value === 'string' && - value !== '' && - !value.match(/[^@]+@[^@]+/)) { - - list.push('__ must match email pattern.'); - } - }, - - site: function(value, list) { - - if (typeof value === 'string' && - value !== '' && - !value.match(/https?:\/\//)) { - - list.push('__ must match URL pattern.'); - } - } - }, - - // Checks array of validators. - - check: function(row, key, value) { - - var list = []; - - var validators = row.validators || []; - - for (var i = 0; i < validators.length; i++) { - - validators[i].call(null, value, list); - } - - var label = key.substring(0, 1).toUpperCase() + - key.substring(1); - - for (var j = 0; j < list.length; j++) { - - list[j] = list[j].replace('__', label); - } - - return list; - } -}; - -// Helper to work with DOM classes. - -var clazz = { - - list: function(element) { - - return element.className.split(/\s+/); - }, - - // Removes element class. - - remove: function(element, cls) { - - var list = clazz.list(element); - - var removed = []; - - for (var i = 0; i < list.length; i++) { - - if (list[i] !== cls && list[i] !== '') { - - removed.push(list[i]); - } - } - - element.className = removed.join(' '); - }, - - // Adds element class. - - add: function(element, cls) { - - var list = clazz.list(element); - - var found = false; - - for (var i = 0; i < list.length; i++) { - - if (list[i] === cls) { - - found = true; - } - } - - if (!found) { - - list.push(cls); - } - - element.className = list.join(' '); - } -}; - -// Helper to manage form errors. - -var errors = { - - // Adds new error. - - display: function(row, message) { - - clazz.add(row.element.parentNode, 'error'); - - row.error = document.createElement('div'); - - row.error.innerHTML = message; - - row.element.parentNode.appendChild(row.error); - }, - - // Removes all errors. - - remove: function(row) { - - var type = row.element.getAttribute('type'); - - // Ignore hidden inputs. - - if (type !== 'hidden') { - - clazz.remove(row.element.parentNode, 'error'); - } - - if (row.error) { - - row.error.parentNode.removeChild(row.error); - - delete row.error; - } - } -}; - -// Helper that processes inputs object. - -var reader = { - - // Reads data from the form descriptor. - - read: function(desc) { - - var valid = true; - - var values = {}; - - reader.each(desc, function(row, key) { - - errors.remove(row); - - var value = input[row.type](row.element); - - var list = validator.check(row, key, value); - - if (list.length > 0) { - - valid = false; - - errors.display(row, list.join(' ')); - } - - if (typeof value !== 'undefined') { - - values[key] = value; - } - }); - - return { values: values, valid: valid }; - }, - - // Runs callback for each input. - - each: function(desc, cb) { - - for (var key in desc) { - - var row = desc[key]; - - // Consider only defined elements. - - if (row.element) { - - cb(row, key); - } - } - } -}; - -module.exports = function(options) { - - if (typeof options.form === 'string') { - - options.form = document.querySelector(options.form); - } - - if (typeof options.question === 'string') { - - options.question = document.querySelector(options.question); - } - - if (!options.form) { - - throw new Error('Comment form element not specified.'); - } - - if (!options.question) { - - throw new Error('Verification question element not specified.'); - } - - if (!options.message) { - - throw new Error('Feedback message/error element not specified.'); - } - - var form = options.form; - - var elements = form.elements; - - var data = { - - post_id: { - - type: 'string', - - element: elements.post_id - }, - - reply_to: { - - type: 'string', - - element: elements.reply_to - }, - - author: { - - type: 'string', - - validators: [ validator.string.is_set ], - - element: elements.author - }, - - email: { - - type: 'string', - - validators: [ validator.string.email ], - - element: elements.email - }, - - site: { - - type: 'string', - - validators: [ validator.string.site ], - - element: elements.site - }, - - content: { - - type: 'string', - - validators: [ validator.string.is_set ], - - element: elements.content - }, - - notify: { - - type: 'check', - - element: elements.notify - }, - - question: { - - type: 'int', - - element: elements.question - }, - - answer: { - - type: 'string', - - validators: [ validator.string.is_set ], - - element: elements.answer - } - }; - - api.question(function(err, response) { - - if (err) { - - - } else { - - // TODO check that question element is set. - // TODO check response status - - options.question.innerHTML = response.data.question; - } - }); - - form.onsubmit = function() { - - var result = reader.read(data); - - console.log(JSON.stringify(result, null, 2)); - - return false; - }; -}; diff --git a/comment/package.json b/comment/package.json deleted file mode 100644 index 76d0c46..0000000 --- a/comment/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "blog-core-comment", - "version": "0.0.1", - "private": true, - "devDependencies": { - "browserify": "4.x", - "exorcist": "^0.3.0", - "jshint": "~2.5.5", - "uglifyify": "^3.0.1", - "brfs": "~1.2.0", - "casperjs": "~1.1.0-beta3" - } -} diff --git a/comment/tests/host.js b/comment/tests/host.js deleted file mode 100644 index 74dc6cd..0000000 --- a/comment/tests/host.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'http://localhost:18008'; diff --git a/comment/tests/stories/validation.js b/comment/tests/stories/validation.js deleted file mode 100644 index 9079603..0000000 --- a/comment/tests/stories/validation.js +++ /dev/null @@ -1,101 +0,0 @@ -var host = require('../host'); - -casper.test.begin('Check validation', function(test) { - - // The start page. Should be quick to load. - - casper.start(host + '/comment.html', function() { - - test.assertTitle('Blog-Core comment system test'); - - casper.viewport(1366, 1200); - }); - - // Checks that no validation error exists. - - casper.then(function() { - - test.assertTextDoesntExist('Email must match email pattern.'); - test.assertTextDoesntExist('Site must match URL pattern.'); - test.assertTextDoesntExist('Author must be set.'); - test.assertTextDoesntExist('Content must be set.'); - test.assertTextDoesntExist('Answer must be set.'); - }); - - casper.thenClick('button[type="submit"]'); - - // Default inputs. - - casper.then(function() { - - test.assertTextExists('Author must be set.'); - test.assertTextExists('Content must be set.'); - test.assertTextExists('Answer must be set.'); - }); - - // Insert author. - - casper.then(function() { - - this.fill('#comment-form', { author: 'Raivo' }, true); - }); - - casper.then(function() { - - test.assertTextExists('Content must be set.'); - test.assertTextExists('Answer must be set.'); - }); - - // Insert invalid mail. - - casper.then(function() { - - this.fill('#comment-form', { email: 'invalid'}, true); - }); - - casper.then(function() { - - test.assertTextExists('Email must match email pattern.'); - }); - - // Insert valid mail. - - casper.then(function() { - - this.fill('#comment-form', { email: 'info@infdot.com'}, true); - }); - - casper.then(function() { - - test.assertTextDoesntExist('Email must match email pattern.'); - }); - - // Insert invalid site. - - casper.then(function() { - - this.fill('#comment-form', { site: 'invalid'}, true); - }); - - casper.then(function() { - - test.assertTextExists('Site must match URL pattern.'); - }); - - // Insert valid site. - - casper.then(function() { - - this.fill('#comment-form', { site: 'http://example.com'}, true); - }); - - casper.then(function() { - - test.assertTextDoesntExist('Site must match URL pattern.'); - }); - - casper.run(function() { - - test.done(); - }); -}); diff --git a/public/comment.html b/public/comment.html deleted file mode 100644 index 2deefe2..0000000 --- a/public/comment.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Blog-Core comment system test - - - - -
- - -
- - -
-
- - -
-
- - -
-
- - -
-
 
-
- - -
-
- -
-
-
-
-
- - - - diff --git a/public/comment.js b/public/comment.js deleted file mode 100644 index 1dd724a..0000000 --- a/public/comment.js +++ /dev/null @@ -1,8 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.bcComment=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0&&(t=!1,errors.display(e,i.join(" "))),"undefined"!=typeof o&&(r[n]=o)}),{values:r,valid:t}},each:function(e,t){for(var r in e){var n=e[r];n.element&&t(n,r)}}};module.exports=function(e){if("string"==typeof e.form&&(e.form=document.querySelector(e.form)),"string"==typeof e.question&&(e.question=document.querySelector(e.question)),!e.form)throw new Error("Comment form element not specified.");if(!e.question)throw new Error("Verification question element not specified.");if(!e.message)throw new Error("Feedback message/error element not specified.");var t=e.form,r=t.elements,n={post_id:{type:"string",element:r.post_id},reply_to:{type:"string",element:r.reply_to},author:{type:"string",validators:[validator.string.is_set],element:r.author},email:{type:"string",validators:[validator.string.email],element:r.email},site:{type:"string",validators:[validator.string.site],element:r.site},content:{type:"string",validators:[validator.string.is_set],element:r.content},notify:{type:"check",element:r.notify},question:{type:"int",element:r.question},answer:{type:"string",validators:[validator.string.is_set],element:r.answer}};api.question(function(t,r){t||(e.question.innerHTML=r.data.question)}),t.onsubmit=function(){var e=reader.read(n);return console.log(JSON.stringify(e,null,2)),!1}}; - - -},{}]},{},[1]) -//# sourceMappingURL=comment.js.map -(1) -}); diff --git a/public/comment.js.map b/public/comment.js.map deleted file mode 100644 index f0222ca..0000000 --- a/public/comment.js.map +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": 3, - "sources": [ - "/home/raivo/blog-core/comment/node_modules/browserify/node_modules/browser-pack/_prelude.js", - "/home/raivo/blog-core/comment/comment.js" - ], - "names": [], - "mappings": "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", - "file": "generated.js", - "sourceRoot": "", - "sourcesContent": [ - "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o