Skip to content

Commit

Permalink
Basic content parsing structure in. No tests, error handling or outpu…
Browse files Browse the repository at this point in the history
…t UI yet.
  • Loading branch information
idmillington committed Sep 24, 2014
1 parent d575a26 commit 9fa439b
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 37 deletions.
158 changes: 122 additions & 36 deletions lib/parsers/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,18 @@
(function() {
"use strict";

var async = require('async');
var assert = require('assert');
var _ = require('lodash');

/*
= Romeo and Juliet
Two households, both alike in dignity //
In fair Verona where we lay our scene //
From ancient grudge break to new mutiny
Where civil blood makes civil hands unclean
From *forth the fatal loins of these two foes
A pair of **starcross'd** lovers take their* life
Whose misadventured piteous overthrows
[? if foo > 1: Doth with their [death bury their] parents' strife? ?]
The [fearful passage of their death-mark'd love
And the continuance of their parents' rage
Which, but their children's end, naught could remove
Is now the two hours passage of our stage.]
> The which if you with patient ears attend, //
> What here shall miss, our toil shall strive to mend.
>> Wm Shakespeare
---
*/
var engine = require('../engine');
var logic = require('./logic');

/*
Key:
*some words* - emphasis
**some words** - strong emphasis
> paragraph - quotation
>> paragraph - attribution
= paragraph - heading
// + <newline> - manual line break
<blank line> - paragraph break
Expand All @@ -50,7 +29,8 @@

var featuresRe =
/\*+|\/\/\n|^[ \t]*\n|^\s*---\s*$|^\s*>>?|^\s*=|\[\??|\??\]|\{\?|\?\}/mg;
var findFeatures = function(text) {

var _findFeatures = function(text) {
var results = [];
var match;
while ((match = featuresRe.exec(text)) !== null) {
Expand All @@ -63,7 +43,7 @@
return results;
};

var createFeatureBoundaries = function(text, features) {
var _createFeatureBoundaries = function(text, features) {
var result = [];
var typeStack = [];
var emphasisStack = [];
Expand Down Expand Up @@ -182,11 +162,11 @@
break;
}
}
add(currentParagraphFeature, 'end', text.length);
add(currentParagraphFeature, 'end', text.length, text.length);
return result;
};

var buildRanges = function(text, features) {
var _buildRanges = function(text, features) {
var top = function(array) {
return array[array.length - 1];
};
Expand Down Expand Up @@ -244,6 +224,80 @@
return result;
};

// Take a pass through the content data structure, turning conditional
// blocks into the correct format.
var _separatePredicates = function(ranges, predicates) {
_.each(ranges, function(range) {
var predicate;

if (range.content !== undefined) {
if (range.type === 'conditional') {
// Valid conditionals should either have 'if ... :' in their
// first content, or 'if' in their first content, Magic in
// their second, and ':' to start their third.
assert(range.content[0].type === undefined);
var match = /^\s*if\s*([^:]+)\s*:\s*(.*)$/.exec(range.content[0]);
if (match) {
range.content[0] = match[2];

var logic = match[1];
predicate = {type:'logic', source:logic};
range.predicate = predicates.length;
predicates.push(predicate);
} else {
assert(range.content[1].type === 'magic');
assert(range.content[2].type === undefined);
assert(range.content[2].substr(0,1) === ':');

var magic = range.content[1].content.join('; ');
range.content.splice(0,3, range.content[2].substr(1).trim());

predicate = {type:'magic', source:magic};
range.predicate = predicates.length;
predicates.push(predicate);
}
}
_separatePredicates(range.content, predicates);
}
});
};

var compile = function(text, callback) {
var features = _findFeatures(text);
if (features.length === 0) return callback(null, text);

var boundaries = _createFeatureBoundaries(text, features);
var ranges = _buildRanges(text, boundaries);
var predicates = [];
_separatePredicates(ranges, predicates);
// Compile the predicates
var fns = async.map(predicates, function(predicate, done) {
if (predicate.type === 'magic') {
var fn = engine.makeFunctionFromSource(predicate.source);
return done(null, fn);
} else {
assert(predicate.type === 'logic');
logic.compilePredicate(predicate.source, function(err, fn) {
if (err) return done(err);
else return done(null, fn);
});
}
}, function(err, compiledPredicates) {
if (err) return callback(err);
else {
var result = {chunks:ranges};
if (compiledPredicates.length) result.predicates = compiledPredicates;
return callback(null, result);
}
});
};

module.exports = {
compile: compile
};

// ------------------------------------------------------------------------

var toHTML = function(ranges) {
var result = [];
_.each(ranges, function(range) {
Expand Down Expand Up @@ -287,7 +341,9 @@
result.push('</span> ');
break;
case 'conditional':
result.push(' <span class="conditional">');
result.push(' <span class="conditional" condition="');
result.push(range.predicate);
result.push('">');
result.push(toHTML(range.content));
result.push('</span> ');
break;
Expand All @@ -308,11 +364,41 @@
return result.join('');
};

var rnj = " = Romeo and Juliet\n\n Two households, both alike in dignity //\n In fair Verona where we lay our scene //\n From ancient grudge break to new mutiny\n Where civil blood makes civil hands unclean\n\n From *forth the fatal loins of these two foes\n A pair of **starcross'd** lovers take their* life\n Whose misadventured piteous overthrows\n [? if {? Q.foo = \"[?]\" ?}: Doth with their [death bury their] parents' strife?]\n\n The [fearful passage of their death-mark'd love\n And the continuance of their parents' rage\n Which, but their children's end, naught could remove\n Is now the two hours passage of our stage.]\n\n > The which if you with patient ears attend,//\n What here shall miss, our toil shall strive to mend.\n >> Wm Shakespeare\n\n ---\nAnd we're done.";
var f = findFeatures(rnj);
var b = createFeatureBoundaries(rnj, f);
var r = buildRanges(rnj, b);
console.log(toHTML(r));
//console.log(JSON.stringify(r, null, 2));

// ------------------------------------------------------------------------
// DEBUG
// ------------------------------------------------------------------------

/*
= Romeo and Juliet
Two households, both alike in dignity //
In fair Verona where we lay our scene //
From ancient grudge break to new mutiny
Where civil blood makes civil hands unclean
From *forth the fatal loins of these two foes
A pair of **starcross'd** lovers take their* life
Whose misadventured piteous overthrows
[? if foo > 1: Doth with their [death bury their] parents' strife? ?]
The [fearful passage of their death-mark'd love
And the continuance of their parents' rage
Which, but their children's end, naught could remove
Is now the two hours passage of our stage.]
> The which if you with patient ears attend, //
> What here shall miss, our toil shall strive to mend.
>> Wm Shakespeare
---
*/
/*
var rnj = " = Romeo and Juliet\n\n Two households, both alike in dignity //\n In fair Verona where we lay our scene //\n From ancient grudge break to new mutiny\n Where civil blood makes civil hands unclean\n\n From *forth the [? if foo > 1: fatal loins of these two ?] foes\n A pair of **starcross'd** lovers take their* life\n Whose misadventured piteous overthrows\n [? if {? return Q.foo === 1 ?}: Doth with their [death bury their] parents' strife?]\n\n The [fearful passage of their death-mark'd love\n And the continuance of their parents' rage\n Which, but their children's end, naught could remove\n Is now the two hours passage of our stage.]\n\n > The which if you with patient ears attend,//\n What here shall miss, our toil shall strive to mend.\n >> Wm Shakespeare\n\n ---\nAnd we're done.";
compile(rnj, function(err, result) {
if (err) console.error(err.toString().red);
console.log(toHTML(result.content), result.predicates);
});
*/
}());
2 changes: 1 addition & 1 deletion lib/parsers/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@

content: {
required: true,
validate: null
validate: validators.validateContent
},
options: {
required: false,
Expand Down
12 changes: 12 additions & 0 deletions lib/parsers/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
var engine = require('../engine');
var dryParser = require('./dry');
var logic = require('./logic');
var content = require('./content');
var propval = dryParser.propval;
var properr = dryParser.properr;
var propline = dryParser.propline;
Expand Down Expand Up @@ -418,6 +419,16 @@
};
};

// ------------------------------------------------------------------------
// Rich content
// ------------------------------------------------------------------------

var validateContent = function(property, callback) {
var val = propval(property);
if (val === undefined) callback(null, undefined);
else content.compile(val, callback);
};

// ------------------------------------------------------------------------
// Specific property types
// ------------------------------------------------------------------------
Expand Down Expand Up @@ -515,6 +526,7 @@
makeEnsureListItemsMatchSchema: makeEnsureListItemsMatchSchema,
makeEnsureListItemsMatchSchemaById: makeEnsureListItemsMatchSchemaById,

validateContent: validateContent,
validateGoTo: validateGoTo
};
}());

0 comments on commit 9fa439b

Please sign in to comment.