diff --git a/devel/js/main.js b/devel/js/main.js index 144156c..69c35f2 100644 --- a/devel/js/main.js +++ b/devel/js/main.js @@ -19,9 +19,15 @@ situation('start', { choices: ['#testing-option'] }); +situation ('return', { + content: 'Choose an option...', + optionText: 'Return', + choices: ['#testing-option'] +}); + situation('functions-as-properties', { - content: (character, system, from) => - ` + content (character, system, from) { + return ` This property of this situation is outputted by a function, which allows us to incorporate variables such as the name of the situation we came from; in this case, "${from}." @@ -30,9 +36,10 @@ situation('functions-as-properties', { functions; the notable exception is optionText. Those functions are passed the character and system objects, in that order, and a third object that is usually either the current situation, or the situation - we just came from.`, + we just came from.`}, tags: ['testing-option'], - optionText: 'Functions as properties' + optionText: 'Functions as properties', + choices: ['return'] }); situation('markdown-features', { @@ -50,7 +57,8 @@ situation('markdown-features', { Additionally, we also support "smart quotes" and -- dashes.`, tags: ['testing-option'], - optionText: 'Markdown support' + optionText: 'Markdown support', + choices: ['return'] }); situation('special-links', { @@ -72,7 +80,8 @@ situation('special-links', { 'inserter-link': "-- like this" }, tags: ['testing-option'], - optionText: 'Special Links' + optionText: 'Special Links', + choices: ['return'] }); situation('custom-actions', { @@ -93,7 +102,8 @@ situation('custom-actions', { } }, tags: ['testing-option'], - optionText: 'Special Actions' + optionText: 'Special Actions', + choices: ['return'] }); situation('randomness', { @@ -108,37 +118,45 @@ situation('randomness', { ${["dog", "cat", "alpaca", "crow"].shuffle(system).join(', ')}. `, tags: ['testing-option'], - optionText: 'Randomness' + optionText: 'Randomness' , + choices: ['return'] }); var myIterators = {}; situation('iterators', { - content: (character, system, from) => - ` - # Iterators + animal: oneOf('cat', 'crow', 'alpaca').cycling(), + content (character, system, from) { + console.log("got here"); + console.log(this); + return ` + # Iterators - Iterators are an useful feature for generating adaptive text. For example, - clicking ${a('this link').writer('iterator')} will output a - new paragraph with a random animal. + Iterators are an useful feature for generating adaptive text. For example, + clicking ${a('this link').writer('iterator')} will output a + new paragraph with a random animal. - Initialising iterators during your init function will make them even more - useful, since it lets you pass the system object on to them to ensure - consistency between saves. For example, ${a('this link') - .writer('consistent')} will produce the same output every - time. + Initialising iterators during your init function will make them even more + useful, since it lets you pass the system object on to them to ensure + consistency between saves. For example, ${a('this link') + .writer('consistent')} will produce the same output every + time. - Other iterators allow you to ${a('cycle').writer('cycler')} through - different content in ${a('various ways').writer('stopper')}. - `, + Other iterators allow you to ${a('cycle').writer('cycler')} through + different content in ${a('various ways').writer('stopper')}. + + And finally, OneOf iterator objects can be used directly in situations: + ${this.animal}. + ` }, writers: { - iterator: oneOf(['Cat', 'Dog', 'Crow', 'Alpaca']).randomly(), + iterator: oneOf('Cat', 'Dog', 'Crow', 'Alpaca').randomly(), consistent: () => myIterators.consistentIterator(), - cycler: oneOf(['Spring', 'Summer', 'Fall', 'Winter']).cycling(), - stopper: oneOf(['First click', 'Second click', 'Another click']).stopping() + cycler: oneOf('Spring', 'Summer', 'Fall', 'Winter').cycling(), + stopper: oneOf('First click', 'Second click', 'Another click').stopping() }, tags: ['testing-option'], - optionText: 'Iterators' + optionText: 'Iterators', + choices: ['return'] }); situation('progress-bar', { @@ -152,7 +170,8 @@ situation('progress-bar', { through Undum's own API. `, tags: ['testing-option'], - optionText: 'Progress bars' + optionText: 'Progress bars', + choices: ['return'] }); qualities({ diff --git a/docs/situation.md b/docs/situation.md index ac37e8d..0cd6d79 100644 --- a/docs/situation.md +++ b/docs/situation.md @@ -92,6 +92,39 @@ The output from the function is taken as a string to be parsed as markdown, and Inside a content function, the value of `this` is bound to the situation object itself, allowing you to refer to properties of the situation. +#### A note about indentation + +Markdown cares about indentation for things such as `
` blocks and nested lists. However, we as programmers care about indentation to keep our code readable. As a compromise between the two, Raconteur will normalise indentation in content strings by doing the following:
+
+- Finding the smallest level of indentation on a non-empty line;
+- Stripping that level of indentation out of every line.
+
+This means that if you write:
+
+```javascript
+`
+  Lorem ipsum dolor sit amet.
+
+    var foo = x;
+`
+```
+
+Then Raconteur will normalise that to:
+
+```markdown
+Lorem ipsum dolor sit amet.
+
+  var foo = x;
+```
+
+So that when this is parsed as markdown, the first line will be a paragraph and the second line will be a code block. If, for some reason, you need an entire situation's content to be a preformatted code block, you can use a fenced code block:
+
+~~~markdown
+```
+This is a fenced code block.
+```
+~~~
+
 ### tags :: Array (from undum.Situation)
 
 A list of tags. See Undum documentation.
diff --git a/lib/situation.js b/lib/situation.js
index 7b9af06..658e13d 100644
--- a/lib/situation.js
+++ b/lib/situation.js
@@ -12,17 +12,25 @@ var undum = require('undum-commonjs'),
 ----------------------------------------------------------------------------*/
 
 /*
-  Normalises the whitespace on a string. So the indentation level of the
-  first line will become 0. FIXME: This isn't quite ideal. Need to figure out
-  a better way of preventing strings in source code ending up interpreted as
-  
 blocks.
+  Normalises the whitespace on a string.
 */
 
 String.prototype.normaliseTabs = function () {
-  let lines = this.split('\n');
-  let indent = lines[0].match(/^\s+/) || lines[1].match(/^\s+/);
-  if (!indent) return this;
-  return lines.map( s => s.replace(new RegExp('^' + indent), '')).join('\n');
+  var lines = this.split('\n');
+  var indents = lines
+    .filter((l) => l !== '') // Ignore empty lines
+    .map((l) => l.match(/^\s+/))
+    .map(function (m) {
+      if (m === null) return '';
+      return m[0];
+    });
+  var smallestIndent = indents.reduce(function(max, curr) {
+    if (curr.length < max.length) return curr;
+    return max;
+  }); // Find the "bottom" indentation level
+  return lines.map(function (l) {
+    return l.replace(new RegExp('^' + smallestIndent), '');
+  }).join('\n');
 };
 
 /* Agnostic Call */