1
0
Fork 0
mirror of https://github.com/Oreolek/raconteur.git synced 2024-05-17 00:08:16 +03:00

Fix indentation normalisation algorithm

This commit is contained in:
Bruno Dias 2015-04-12 15:08:18 -03:00
parent 6ef13e2094
commit bb6e302857
3 changed files with 95 additions and 35 deletions

View file

@ -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({

View file

@ -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 `<pre>` 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.

View file

@ -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
<pre> 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 */