Commit 2b8caa6b authored by Leon Arnott's avatar Leon Arnott
Browse files

Updated some documentation, and decided to raise the version number to 3.0.

I've decided the amount of alterations is major enough to justify this numeric increase.

The "design history" section of the documentation is still not complete, so it's being commented out for now.
parent e189559b03da
Copyright (c) 2015 Leon Arnott
Copyright (c) 2018 Leon Arnott
This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use
......
......@@ -2,7 +2,7 @@
Rough documentation is at http://twine2.neocities.org/. See below for compilation instructions.
###2.2.0 changes:
###3.0.0 changes:
####Bugfixes
......
window.storyFormat({"name":"Harlowe","version":"2.2.0","author":"Leon Arnott","description":"The default story format for Twine 2. See its <a href='http://twine2.neocities.org/' target='_blank' rel='noopener noreferrer'>documentation</a>.","image":"icon.svg","url":"http://twinery.org/","license":"Zlib","proofing":false,"source":"","setup":""});
\ No newline at end of file
window.storyFormat({"name":"Harlowe","version":"3.0.0","author":"Leon Arnott","description":"The default story format for Twine 2. See its <a href='http://twine2.neocities.org/' target='_blank' rel='noopener noreferrer'>documentation</a>.","image":"icon.svg","url":"http://twinery.org/","license":"Zlib","proofing":false,"source":"","setup":""});
\ No newline at end of file
......@@ -8,7 +8,7 @@ define(['utils', 'utils/operationutils', 'internaltypes/varref', 'internaltypes/
*/
/*d:
Bound Variable data
Bind data
A few macros that produce interactive elements, like (cycling-link:), have the ability to automatically update a variable whenever the
player interacts with them. There needs to be a way to specify which variable these will update: simply giving the macro the variable
......
......@@ -36,7 +36,7 @@
/*
The mode is defined herein.
*/
window.CodeMirror && CodeMirror.defineMode('harlowe-2', () => {
window.CodeMirror && CodeMirror.defineMode('harlowe-3', () => {
let cm, tree,
// These caches are used to implement special highlighting when the cursor
// rests on variables or hookRefs, such that all the other variable/hook
......@@ -127,7 +127,7 @@
cursorMarks.push(doc.markText(
doc.posFromIndex(token.start),
doc.posFromIndex(token.end),
{className: 'cm-harlowe-2-cursor'}
{className: 'cm-harlowe-3-cursor'}
));
/*
If the token is a variable or hookRef, then
......@@ -144,7 +144,7 @@
cursorMarks.push(doc.markText(
doc.posFromIndex(e.start),
doc.posFromIndex(e.end),
{className: 'cm-harlowe-2-variableOccurrence'}
{className: 'cm-harlowe-3-variableOccurrence'}
));
}
});
......@@ -166,7 +166,7 @@
cursorMarks.push(doc.markText(
doc.posFromIndex(tagStart),
doc.posFromIndex(tagStart + e.name.length),
{className: 'cm-harlowe-2-hookOccurrence'}
{className: 'cm-harlowe-3-hookOccurrence'}
));
}
});
......@@ -213,7 +213,7 @@
TwineJS's PassageEditor stashes a reference to the CodeMirror instance in
the Harlowe modes object - and here, we retrieve it.
*/
cm = CodeMirror.modes['harlowe-2'].cm;
cm = CodeMirror.modes['harlowe-3'].cm;
cm.setOption('placeholder', [
"Enter the body text of your passage here.",
"''Bold'', //italics//, ^^superscript^^, ~~strikethrough~~, and <p>HTML tags</p> are available.",
......@@ -284,7 +284,7 @@
let ret = '';
for (let i = 0; i < currentBranch.length; i+=1) {
const type = currentBranch[i].type;
let name = "harlowe-2-" + type;
let name = "harlowe-3-" + type;
counts[name] = (counts[name] || 0) + 1;
// If this name has been used earlier in the chain, suffix
// this name with an additional number.
......@@ -298,7 +298,7 @@
*/
case "macroName":
if (validMacros.indexOf(insensitiveName(currentBranch[i].text.slice(0,-1))) === -1) {
name += " harlowe-2-error";
name += " harlowe-3-error";
}
break;
}
......@@ -317,10 +317,10 @@
If the style element already exists, it is reused. Otherwise, it's created.
(Let's use pure DOM calls in the absence of a jQuery require() call.)
*/
let harloweStyles = document.querySelector('style#cm-harlowe-2');
let harloweStyles = document.querySelector('style#cm-harlowe-3');
if (!harloweStyles) {
harloweStyles = document.createElement('style');
harloweStyles.setAttribute('id','cm-harlowe-2');
harloweStyles.setAttribute('id','cm-harlowe-3');
document.head.appendChild(harloweStyles);
}
/*
......@@ -345,7 +345,7 @@
root: 'box-sizing:border-box;',
// The cursor token highlight should ignore the most common tokens, unwrapped text tokens.
"cursor:not([class^='cm-harlowe-2-text cm-harlowe-2-root'])":
"cursor:not([class^='cm-harlowe-3-text cm-harlowe-3-root'])":
"border-bottom: 2px solid darkgray;",
CodeMirror: "padding: 0 !important",
......@@ -370,7 +370,7 @@
"font-weight:bold;",
//TODO: whitespace within collapsed
"error:not([class*='cm-harlowe-2-string'])":
"error:not([class*='cm-harlowe-3-string'])":
invalid,
macro: macro(0.05),
......@@ -509,9 +509,9 @@
}
// There's no need for $= because that will always be cm-harlowe-root or cm-harlowe-cursor.
if (e.indexOf("^=") === 0) {
return "[class^='cm-harlowe-2-" + e.slice(2) + "']";
return "[class^='cm-harlowe-3-" + e.slice(2) + "']";
}
return ".cm-harlowe-2-" + e;
return ".cm-harlowe-3-" + e;
});
return a + selector.join(', ') + "{" + this[e] + "}";
}, '');
......
Appendix: Summarised history of Harlowe's design
Disabled Appendix: Summarised history of Harlowe's design
You may have a number of questions about various aspects of Harlowe's design. For posterity, I'd like to use this section to chronicle my motivations for most of Harlowe's major divergences from Twine 1, point out several of its outside inspirations, and describe how several of its own idiosyncracies came to be.
......
Introduction: Some of what's new in 2.0
Introduction: Some of what's new in 3.0
A lot of features have been added to Harlowe 2.0, many of which are designed to shorten existing code idioms or make certain workarounds unnecessary. The changes to existing features you should first familiarise yourself with are:
Harlowe 3.0, while not as major an upgrade as 2.0, offers a few new features that deserve your attention:
* The default Harlowe colour scheme is now white text on black, in adherence to SugarCube and Sugarcane. You can change it back to white using the instructions below.
* Expressions like `$a < 4 and 5` will now be interpreted as `$a < 4 and it < 5` instead of always producing an error.
* Using `is` with comparison operators, like `$a is < 3`, is now valid.
* Changers can be attached to hooks with whitespace between them - `(if: $coverBlown) [Run!]` is now valid.
* Changers can be attached to named hooks - `(if: true) |moths>[Several moths!]` is now valid.
* Changers can be added together using + while attaching them to a hook - `(font:'Shatter')+(text-style:'outline')[CRASH!]` is now valid.
* The default CSS has been changed such that the story's `font` must be overridden on `tw-story` rather than `html` (for consistency with other CSS properties).
* New form input macros have been added, similar to those available in Twine 1.4 and SugarCube. They use a new keyword, <a href="#type_bind">bind</a>, to automatically set a variable when they're interacted with.
* (cycling-link:) reappears after a long absence since Twine 1.4.
* (dropdown:) produces a dropdown menu.
* You can now attach changers to ordinary links and other commands, rather than just hooks.
* Passage transitions can now be changed on a per-link basis - instead of the normal fade-in, a number of other transitions can be used. Simply attach (t8n-depart:) or (t8n-arrive:) to the passage link.
* New transitions are available: "instant", "rumble", "slide-up", "slide-down", "slide-left", "slide-right" and "flicker".
* New `is a` and `matches` operators are available to compare data structures' similarity, or to check the <a href="#type_datatype">datatype</a> of variables.
The following new features also deserve your attention.
* The built-in `?page`, `?passage`, `?sidebar` and `?link` hooks
* Hidden hooks, and the (show:) and (hidden:) command macros
* Temp variables (see the (set:) article)
* The special `any` and `all` data names for arrays, strings and datasets (see each type's articles)
* The (for:) changer macro
* The (enchant:) command macro
* The (find:), (altered:) and (folded:) data macros
* The (dm:) and (ds:) aliases for (datamap:) and (dataset:)
* Column markup
* `tw-passage` elements now have a `tags` attribute.
For a complete list of changes, consult the <a href="#changes_2.0.0-changes-(also-see-1.2.3-changes)">change log</a> section.
Changing back from dark to light:
You may want to use the black-on-white colour scheme of Harlowe 1 instead of the new white-on-black colour scheme. A few of the new features described above can help you do this without using CSS! Simply create a `header` tagged passage (a passage with the tag 'header'), and include this in it:
```
(enchant: ?page, (text-colour: black) + (background: white))
```
This uses the new ?page built-in hook to target the entire page, and the new (enchant:) macro to apply changer commands to it directly. In the future, more features are planned that will allow styling the page in this way without CSS, staying within Harlowe code, and letting you use variables and other macros inside it.
For a complete list of changes and outlines of how to use the above features, consult the <a href="#changes_3.0.0-changes">change log</a> section.
{
"name": "twine-harlowe",
"version": "2.2.0",
"version": "3.0.0",
"author": "Leon Arnott",
"description": "The default runtime for Twine 2 stories",
"license": "Zlib",
......@@ -23,23 +23,23 @@
"node": ">=6.0"
},
"dependencies": {
"almond": "latest",
"almond": "0.3",
"es6-shim": "latest",
"jquery": "latest",
"jquery": "3",
"requestanimationframe": "*"
},
"devDependencies": {
"babel-cli": "^6",
"babel-preset-es2015": "^6",
"chalk": "latest",
"fs-readdir-recursive": "latest",
"jshint": "latest",
"chalk": "2",
"fs-readdir-recursive": "1",
"jshint": "2",
"marked": "0.3.3",
"requirejs": "latest",
"requirejs": "2",
"jasmine-core": "2.4",
"replacestream": "latest",
"replacestream": "4",
"uglify-js": "2",
"lodash.unescape": "latest",
"lodash.escape": "latest"
"lodash.unescape": "4",
"lodash.escape": "4"
}
}
......@@ -15,7 +15,7 @@ let navElement = "<nav><img src='icon.svg' width=96 height=96></img>";
*/
const {version} = JSON.parse(fs.readFileSync('package.json'));
navElement += `<div class=nav_version><p>Harlowe ${version} manual</p>
<p><a href="/1.html">1.2.4</a> | <b>${version}</b></p>
<p><a href="/1.html">1.2.4</a> | <a href="/2.html">2.1.0</a> | <b>${version}</b></p>
</div>`;
let currentCategory;
......@@ -76,7 +76,7 @@ outputFile = outputFile.replace(/<code>([^<]+)<\/code>(~?)/g, ({length}, code, n
return `<code>${code}</code>`;
}
function makeCSSClasses(pos) {
return root.pathAt(pos + root.start).map(token => 'cm-harlowe-2-' + token.type).join(' ');
return root.pathAt(pos + root.start).map(token => 'cm-harlowe-3-' + token.type).join(' ');
}
code = unescape(code);
let ret = '', root, lastPos = 0;
......
......@@ -14,7 +14,7 @@ const
it seems to be part of a macro name.
Due to its commonality in English, "any" is not included.
*/
typeName = /([^\-`])\b(hookname|colour|variabletovalue|lambda|changer|command|string|number|boolean|array|data(?:map|set))(s?)(?!\:\))\b/ig,
typeName = /([^\-`])\b(hookname|colour|variabletovalue|lambda|changer|command|string|bind|datatype|number|boolean|array|data(?:map|set))(s?)(?!\:\))\b/ig,
Defs = function(props) {
return Object.assign({
......
......@@ -34,6 +34,29 @@ describe("enchantment macros", function () {
done();
},400);
});
it("enchants (link:) links", function(done) {
var p = runPassage("(enchant:?Link,(text-style:'italic')+(color:'#800000'))(link:'foo')[bar]");
setTimeout(function() {
var enchantment = p.find('tw-link').parent();
expect(enchantment.css('color')).toMatch(/(?:#800000|rgb\(\s*128,\s*0,\s*0\s*\))/);
expect(enchantment.css('font-style')).toMatch(/italic/);
p.find('tw-link').click();
expect(p.text()).toBe('bar');
done();
},400);
});
it("works in 'header' tagged passages", function(done) {
createPassage("(enchant: ?Link, (text-style:'italic')+(color:'#800000'))","","header");
var p = runPassage("(link:'foo')[bar]");
setTimeout(function() {
var enchantment = p.find('tw-link').parent();
expect(enchantment.css('color')).toMatch(/(?:#800000|rgb\(\s*128,\s*0,\s*0\s*\))/);
expect(enchantment.css('font-style')).toMatch(/italic/);
p.find('tw-link').click();
expect(p.text()).toBe('bar');
done();
},400);
});
});
describe("enchanting ?Page", function() {
it("wraps the ?Page in a <tw-enchantment>", function(done) {
......
......@@ -39,7 +39,7 @@ window.createPassage = function(text, name, tags) {
Passages.set(name, new Map([
["source", text],
["name", name],
["tags", tags],
["tags", tags ? [tags] : undefined],
]));
};
window.goToPassage = function(text, name) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment