fractive
Version:
Fractive is a hypertext authoring tool, primarily intended for the creation of interactive fiction.
720 lines (657 loc) • 51.5 kB
HTML
<html>
<head>
<title>Basic Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta property="og:title" content="Basic Example" />
<meta property="og:description" content="An interactive story written in Fractive" />
<meta name="twitter:card" content="summary" />
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"></link>
<style>
#__controls {
position: fixed;
top: 0px;
left: 0px;
width: calc(100% - 80px);
height: 75px;
padding: 0px 40px;
background-color: #333333;
color: #BBBBBB;
font-family: Arial, Helvetica, sans-serif;
font-size: 13pt;
}
#__controls .controls-left {
float: left;
text-align: left;
}
#__controls .controls-right {
float: right;
text-align: right;
}
#__controls a:link,
#__controls a:visited {
color: #FAFAFA;
text-decoration: none;
}
#__controls a:active,
#__controls a:hover {
color: #FF6666;
text-decoration: none;
}
#__historyContainer {
position: fixed;
top: 75px;
left: 0px;
height: 400px;
width: 100%;
overflow: auto;
background-color: #333333;
}
#__history * {
max-width: 750px !important;
margin-left: auto !important;
margin-right: auto !important;
color: #777777 !important;
font-family: Arial, Helvetica, sans-serif !important;
font-size: 13pt !important;
}
#__history .__inlineMacro {
animation: none;
color: #777777;
}
.__disabledLink {
color: #777777;
text-decoration: underline;
}
#__content {
position: absolute;
top: 75px;
left: 0px;
width: 100%;
overflow: auto;
}
#__currentSection {
color: #555555;
animation: 1s textFadeIn;
max-width: 900px;
margin-left: auto;
margin-right: auto;
}
@keyframes textFadeIn {
from {
color: #FAFAFA;
}
to {
color: #555555;
}
}
.__inlineMacro {
animation: 1s inlineMacroFadeIn;
color: #a7826a;
}
@keyframes inlineMacroFadeIn {
from {
color: #FAFAFA;
}
to {
color: #a7826a;
}
}
h1 {
font-family: Arial, Helvetica, sans-serif;
font-size: 56pt;
margin-top: 28pt;
margin-bottom: -4pt;
line-height: 0.9em;
}
h2 {
font-family: Arial, Helvetica, sans-serif;
font-size: 38pt;
margin-top: 19pt;
margin-bottom: -12pt;
}
h3 {
font-family: Arial, Helvetica, sans-serif;
font-size: 22pt;
text-transform: uppercase;
margin-top: 11pt;
margin-bottom: -8pt;
}
body {
background-color: #FAFAFA;
}
p {
font-family: Arial, Helvetica, sans-serif;
font-size: 16pt;
line-height: 1.5em;
}
a:link,
a:visited {
color: #6666FF;
}
a:active,
a:hover {
color: #FF6666;
}
li {
font-family: Arial, Helvetica, sans-serif;
font-size: 16pt;
line-height: 1.5em;
margin-left: 20px;
}
blockquote p {
font-family: Arial, Helvetica, sans-serif;
font-size: 16pt;
font-style: italic;
line-height: 1.5em;
}
pre {
font-family: "Courier New", "Courier", monospace;
font-size: 14pt;
background-color: #333333;
color: #BBBBBB;
line-height: 1.5em;
padding: 10px 20px;
max-height: 600px;
overflow: auto;
}
img {
margin: 20px 0px;
}
hr {
border: 0;
height: 1px;
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));
margin-top: 36pt;
margin-bottom: 36pt;
}
</style>
<script>
var exports = {};
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var Core;
(function(Core) {
var EGotoSectionReason;
(function(EGotoSectionReason) {
EGotoSectionReason[EGotoSectionReason["Goto"] = 0] = "Goto";
EGotoSectionReason[EGotoSectionReason["Back"] = 1] = "Back";
EGotoSectionReason[EGotoSectionReason["Refresh"] = 2] = "Refresh";
})(EGotoSectionReason = Core.EGotoSectionReason || (Core.EGotoSectionReason = {}));
var OnBeginStory = [];
var OnGotoSection = [];
var currentSectionObserver = new MutationObserver(OnCurrentSectionModified);
var currentSectionObserverConfig = {
childList: true,
attributes: true,
characterData: true,
subtree: true
};
function ActivateElement(element) {
if (element.tagName && element.tagName.toLowerCase() == "a") {
var _loop_1 = function(i) {
switch (element.attributes[i].name) {
case "data-goto-section":
{
element.addEventListener("click", function() {
Core.GotoSection(element.attributes[i].value);
});
break;
}
case "data-call-function":
{
element.addEventListener("click", RetrieveFromWindow(element.attributes[i].value, 'function'));
break;
}
case "data-replace-with":
{
element.addEventListener("click", function() {
Core.ReplaceActiveElement(element.id, ExpandMacro(element.attributes[i].value));
});
break;
}
}
};
for (var i = 0; i < element.attributes.length; i++) {
_loop_1(i);
}
}
if (element.id && element.id !== "__currentSection") {
if (element.id[0] !== '!') {
element.id = "!" + element.id;
}
}
if (element.children) {
for (var i = 0; i < element.children.length; i++) {
ActivateElement(element.children[i]);
}
}
}
Core.ActivateElement = ActivateElement;
function AddEventListener(eventName, handler) {
switch (eventName) {
case "OnBeginStory":
{
OnBeginStory = OnBeginStory.concat(handler);
break;
}
case "OnGotoSection":
case "OnGoToSection":
{
OnGotoSection = OnGotoSection.concat(handler);
break;
}
default:
{
console.error("Core.AddEventListener: \"" + eventName + "\" is not a valid event");
break;
}
}
}
Core.AddEventListener = AddEventListener;
function BeginStory() {
for (var i = 0; i < OnBeginStory.length; i++) {
OnBeginStory[i]();
}
GotoSection("Start");
}
Core.BeginStory = BeginStory;
function CanBeInline(html, context) {
var root = document.createElement("span");
if (context) {
context.appendChild(root);
} else {
document.appendChild(root);
}
root.innerHTML = html;
var scan = function(e) {
if (getComputedStyle(e, "").display === "block") {
return false;
}
for (var i = 0; i < e.children.length; i++) {
if (scan(e.children[i]) === false) {
return false;
}
}
return true;
};
var result = scan(root);
if (context) {
context.removeChild(root);
} else {
document.removeChild(root);
}
return result;
}
function DisableLinks(section) {
var links = section.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
var linkTag = links[i].outerHTML.substring(0, links[i].outerHTML.indexOf(">") + 1);
var contents = links[i].outerHTML.substring(links[i].outerHTML.indexOf(">") + 1, links[i].outerHTML.indexOf("</a>"));
links[i].outerHTML = "<span class=\"__disabledLink\" data-link-tag='" + linkTag + "'>" + contents + "</span>";
}
}
function EnableLinks(section) {
var links = section.getElementsByClassName("__disabledLink");
for (var i = 0; i < links.length;) {
var linkTag = links[i].getAttribute('data-link-tag');
var contents = links[i].innerHTML;
links[i].outerHTML = linkTag + contents + '</a>';
}
}
function ExpandMacro(macro) {
switch (macro[0]) {
case '@':
{
var sectionName = macro.substring(1);
if (!document.getElementById(sectionName)) {
return "{section \"" + sectionName + "\" is not declared}";
} else {
return ExpandSection(macro.substring(1)).innerHTML;
}
}
case '#':
{
var functionName = macro.substring(1);
var targetFunction = RetrieveFromWindow(functionName, 'function');
if (targetFunction !== null && targetFunction !== undefined) {
var result = targetFunction();
return (result ? result.toString() : "");
} else {
return "{function \"" + functionName + "\" is not defined}";
}
}
case '$':
{
var variableName = macro.substring(1);
var targetVariable = RetrieveFromWindow(variableName, 'variable');
if (targetVariable !== null && targetVariable !== undefined) {
return targetVariable.toString();
} else {
return "{variable \"" + variableName + "\" is not defined}";
}
}
default:
{
return "{unknown metacharacter in macro \"" + macro + "\"";
}
}
}
Core.ExpandMacro = ExpandMacro;
function ExpandSection(id) {
var source = document.getElementById(id);
if (source === null) {
console.log("Section " + id + " doesn't exist");
return null;
}
var sectionInstance = source.cloneNode(true);
sectionInstance.removeAttribute("hidden");
var scan = function(element) {
for (var i = 0; i < element.attributes.length; i++) {
var expanded = false;
switch (element.attributes[i].name) {
case "data-expand-macro":
{
if (element.parentElement) {
var newElement = document.createElement("span");
newElement.innerHTML = ExpandMacro(element.attributes[i].value);
element.parentElement.replaceChild(newElement, element);
expanded = true;
}
break;
}
case "data-image-source-macro":
{
element.setAttribute("src", ExpandMacro(element.attributes[i].value));
expanded = true;
}
}
if (expanded) {
break;
}
}
if (element.hasChildNodes) {
for (var i = 0; i < element.children.length; i++) {
scan(element.children[i]);
}
}
};
scan(sectionInstance);
return sectionInstance;
}
function GetCurrentSectionTags() {
return GetSectionTags("__currentSection");
}
Core.GetCurrentSectionTags = GetCurrentSectionTags;
function GetSection(id) {
var clone = ExpandSection(id);
clone.setAttribute('data-id', id);
return clone;
}
Core.GetSection = GetSection;
function GetSectionsWithTag(tag) {
var matchingSections = [];
var sections = document.getElementsByClassName("section");
for (var i = 0; i < sections.length; ++i) {
var sectionId = sections[i].getAttribute('id');
var sectionTags = GetSectionTags(sectionId);
if (sectionTags.indexOf(tag) !== -1) {
matchingSections.push(sectionId);
}
}
return matchingSections;
}
Core.GetSectionsWithTag = GetSectionsWithTag;
function GetSectionTags(id) {
var sectionDiv = document.getElementById(id);
var tagDeclarations = sectionDiv.getAttribute("data-tags");
return tagDeclarations.split(',');
}
Core.GetSectionTags = GetSectionTags;
function GotoPreviousSection() {
currentSectionObserver.disconnect();
var history = document.getElementById("__history");
if (history === null) {
console.error("History is not supported in this template (the __history element is missing)");
return;
}
var previousSections = history.getElementsByClassName('__previousSection');
var previousSection = previousSections[previousSections.length - 1];
if (!previousSection) {
return;
}
var id = previousSection.getAttribute('data-id');
var clone = previousSection.cloneNode(true);
EnableLinks(clone);
SetElementAsCurrentSection(clone);
for (var i = 0; i < OnGotoSection.length; i++) {
OnGotoSection[i](id, clone, GetSectionTags(id), EGotoSectionReason.Back);
}
history.removeChild(previousSection);
}
Core.GotoPreviousSection = GotoPreviousSection;
function GoToPreviousSection() {
GotoPreviousSection();
}
Core.GoToPreviousSection = GoToPreviousSection;
function GotoSection(id) {
currentSectionObserver.disconnect();
var currentSection = document.getElementById("__currentSection");
DisableLinks(currentSection);
var history = document.getElementById("__history");
var previousSectionId = currentSection.getAttribute('data-id');
if (previousSectionId !== null && history !== null) {
history.innerHTML += "<div class=\"__previousSection\" data-id=\"" + previousSectionId + "\">" + currentSection.innerHTML + "</div>";
history.scrollTop = history.scrollHeight;
}
var clone = GetSection(id);
SetElementAsCurrentSection(clone);
for (var i = 0; i < OnGotoSection.length; i++) {
OnGotoSection[i](id, clone, GetSectionTags(id), EGotoSectionReason.Goto);
}
}
Core.GotoSection = GotoSection;
function GoToSection(id) {
GotoSection(id);
}
Core.GoToSection = GoToSection;
function OnCurrentSectionModified(mutations) {
for (var i = 0; i < mutations.length; i++) {
for (var j = 0; j < mutations[i].addedNodes.length; j++) {
var e = mutations[i].addedNodes[j];
ActivateElement(e);
}
}
}
function RefreshCurrentSection() {
currentSectionObserver.disconnect();
var currentSection = document.getElementById("__currentSection");
var id = currentSection.getAttribute("data-id");
var clone = GetSection(id);
SetElementAsCurrentSection(clone);
for (var i = 0; i < OnGotoSection.length; i++) {
OnGotoSection[i](id, clone, GetSectionTags(id), EGotoSectionReason.Refresh);
}
}
Core.RefreshCurrentSection = RefreshCurrentSection;
function RetrieveFromWindow(name, type) {
var targetObject = null;
var tokens = name.split('.');
for (var i = 0; i < tokens.length; i++) {
if (i === 0) {
targetObject = window[tokens[0]];
} else {
targetObject = targetObject[tokens[i]];
}
}
if (targetObject === undefined) {
return "{" + type + " \"" + name + "\" is not declared}";
}
return targetObject;
}
function ReplaceActiveElement(id, html) {
var element = document.getElementById(id[0] === '!' ? id : "!" + id);
if (!element) {
return;
}
var replacement = document.createElement(CanBeInline(html, element.parentElement) ? "span" : "div");
replacement.className = "__inlineMacro";
replacement.innerHTML = html;
ActivateElement(replacement);
element.parentNode.replaceChild(replacement, element);
}
Core.ReplaceActiveElement = ReplaceActiveElement;
function SetElementAsCurrentSection(e) {
var currentSection = document.getElementById("__currentSection");
e.scrollTop = 0;
e.id = "__currentSection";
ActivateElement(e);
currentSection.parentElement.replaceChild(e, currentSection);
currentSectionObserver.observe(e, currentSectionObserverConfig);
}
})(Core = exports.Core || (exports.Core = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9Db3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBc0JBLElBQWlCLElBQUksQ0EwaEJwQjtBQTFoQkQsV0FBaUIsSUFBSTtJQUVwQixJQUFZLGtCQUtYO0lBTEQsV0FBWSxrQkFBa0I7UUFFN0IsMkRBQUksQ0FBQTtRQUNKLDJEQUFJLENBQUE7UUFDSixpRUFBTyxDQUFBO0lBQ1IsQ0FBQyxFQUxXLGtCQUFrQixHQUFsQix1QkFBa0IsS0FBbEIsdUJBQWtCLFFBSzdCO0lBS0QsSUFBSSxZQUFZLEdBQXVCLEVBQUUsQ0FBQztJQVMxQyxJQUFJLGFBQWEsR0FBbUcsRUFBRSxDQUFDO0lBSXZILElBQUksc0JBQXNCLEdBQXNCLElBQUksZ0JBQWdCLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUMvRixJQUFJLDRCQUE0QixHQUFHO1FBQ2xDLFNBQVMsRUFBRSxJQUFJO1FBQ2YsVUFBVSxFQUFFLElBQUk7UUFDaEIsYUFBYSxFQUFFLElBQUk7UUFDbkIsT0FBTyxFQUFFLElBQUk7S0FDYixDQUFBO0lBT0QseUJBQWdDLE9BQWlCO1FBR2hELEVBQUUsQ0FBQSxDQUFDLE9BQU8sQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsSUFBSSxHQUFHLENBQUMsQ0FDM0QsQ0FBQztvQ0FDUSxDQUFDO2dCQUVSLE1BQU0sQ0FBQSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQ2xDLENBQUM7b0JBQ0EsS0FBSyxtQkFBbUI7d0JBQ3hCLENBQUM7NEJBQ0EsT0FBTyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRTtnQ0FDakMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDOzRCQUMvQyxDQUFDLENBQUMsQ0FBQzs0QkFDSCxLQUFLLENB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// source/script.js
function HideHistory() {
Core.ShowHistory(false);
}
function FunctionLink() {
alert("It might look like this, if your function was programmed to raise a browser alert (as this one was). Other functions could do complex logic to choose different sections to go to based on things like player state (do you have a certain item in your inventory?) or even a random roll of the dice!");
}
function VariableLink() {
alert("You'll actually get a compiler error, because it doesn't make sense to link to a variable. In this case, I've linked to a function instead; specifically, one that shows you this alert.");
}
function InlineFunction() {
return "This paragraph is some inline text that comes from a function call! In this case, I put a \
function macro in my story text, then had the function return the text I wanted to display. In a real \
game, you could have the function do some kind of game logic that decides what to display; for instance, \
you could have it check if the player has a particular inventory item, and say one thing if they do \
and something different if they don't.";
}
var InlineVariable = "\"Hello, world!\"";
function RaiseAlert() {
alert("fractive is super cool!");
}
function InlineExpansionFunction() {
return "function (functions should return the string that will replace the link)";
}
var InlineExpansionVariable = "variable (a string which will replace the link)";
</script>
<script>
function __Restart() {
location.reload();
}
function __ToggleHistory() {
var historyContainerDiv = document.getElementById("__historyContainer");
if (!historyContainerDiv) {
return;
}
var historyDiv = document.getElementById("__history");
if (!historyDiv) {
return;
}
var contentDiv = document.getElementById("__content");
if (!contentDiv) {
return;
}
// Toggle history visibility
historyContainerDiv.hidden = !historyContainerDiv.hidden;
historyDiv.hidden = historyContainerDiv.hidden;
// Scroll to bottom of history
historyContainerDiv.scrollTop = historyContainerDiv.scrollHeight;
// Adjust content position relative to history panel
var contentTop = 75 + (historyContainerDiv.hidden ? 0 : 425);
contentDiv.style.setProperty("top", contentTop);
contentDiv.style.setProperty("height", window.innerHeight - contentTop);
}
Core.AddEventListener("OnGotoSection", function(id, element, tags, reason) {
// Scroll to bottom of history
var historyContainerDiv = document.getElementById("__historyContainer");
if (historyContainerDiv) {
historyContainerDiv.scrollTop = historyContainerDiv.scrollHeight;
}
// Scroll to top of new content
var contentDiv = document.getElementById("__content");
if (contentDiv) {
contentDiv.scrollTop = 0;
}
});
</script>
</head>
<body>
<div id="__content">
<!-- source/text.md -->
<div id="Start" data-tags="" class="section" hidden="true">
<h1>Welcome!</h1>
<p>Welcome to Fractive, a tool for creating hypertext fiction!</p>
<p>Fractive stories are written in Markdown, and you can add (optional) game logic in Javascript. Stories consist of “sections”, which you might think of like one page of a book. Typically a section will give you a bit of narrative and then present
one or more choices to the player; each choice takes the story to a different section, and in a different direction.</p>
<p>In Markdown, you declare the beginning of a new section by enclosing the section name (which must be unique!) in double curly braces. The section you’re reading right now is called <code>{{Start}}</code> which is a special section name that
indicates where the story begins.</p>
<p><a title="{@AnotherSection}" href="javascript:;" data-goto-section="AnotherSection">Link to another section</a></p>
</div>
<div id="AnotherSection" data-tags="" class="section" hidden="true">
<p>You just clicked a link that took you to another section! You create section links just like any ol’ Markdown link, but in place of the URL you put a special <em>macro</em> enclosed in single curly braces. There are three types of macros,
each denoted by a symbol:</p>
<ul>
<li>@ denotes a section name to link to</li>
<li># denotes a Javascript function to call</li>
<li>$ denotes a Javascript variable</li>
</ul>
<p>So if you set the URL to <code>{@Start}</code> you’d have created a link back to the section called <code>Start</code>. If on the other hand you’d put <code>{#Start}</code> you’d have created a link that would call a Javascript function called
<code>Start</code>.</p>
<p><a title="{#FunctionLink}" href="javascript:;" data-call-function="FunctionLink">What does it look like when a link calls a Javascript function?</a><br/><a title="{#VariableLink}" href="javascript:;" data-call-function="VariableLink">What happens if I set the link URL to a variable macro?</a><br/>
<a
title="{@InlineMacros}" href="javascript:;" data-goto-section="InlineMacros">What else can I use macros for?</a>
</p>
</div>
<div id="InlineMacros" data-tags="" class="section" hidden="true">
<p>Macros aren’t only for links; you can also use them to add dynamic text to your sections.</p>
<blockquote>
<p><span data-expand-macro="#InlineFunction"></span></p>
</blockquote>
<p>The above paragraph was the result of inlining a function call, which expects the function to return a string. You can also inline the value of a variable. Here’s one: <span data-expand-macro="$InlineVariable"></span></p>
<p>You can even inline an entire section:</p>
<blockquote>
<p><span data-expand-macro="@InlineSection"></span></p>
</blockquote>
<p>The inlined function and section above are indented, but that’s only because I prefaced them with the Markdown blockquote indicator for clarity. Inlines don’t inherently get any special styling, so you can inline things totally seamlessly
and your players will never know the difference.</p>
<p>Finally, you can create links which expand to text in-place, which is commonly used in e.g. <a title="https://twinery.org/2/" target="_blank" href="https://twinery.org/2/">Twine <i class="fa fa-external-link" aria-hidden="true"></i></a> games for artistic effect. You can link to a <a title="{$InlineExpansionVariable:inline}" href="javascript:;" data-replace-with="$InlineExpansionVariable" id="inline-0">variable</a>, or to the return value of a <a title="{#InlineExpansionFunction:inline}"
href="javascript:;" data-replace-with="#InlineExpansionFunction" id="inline-1">function</a>, and they’ll expand in-place.</p>
<p><a title="{@InlineExpansionSection:inline}" href="javascript:;" data-replace-with="@InlineExpansionSection" id="inline-2">You can also do this with a section</a></p>
<p><a title="{@AboutFormatting}" href="javascript:;" data-goto-section="AboutFormatting">Can I use Markdown styling?</a></p>
</div>
<div id="InlineSection" data-tags="" class="section" hidden="true">
<p>This paragraph was written in an entirely different section, but it appears as part of the section you’re already reading. This might be useful if you have some boilerplate text that needs to follow the player around from place to place; you
could put it in a section and inline it, instead of copy-pasting the same sentences (or paragraphs) all over your story text.</p>
</div>
<div id="InlineExpansionSection" data-tags="" class="section" hidden="true">
<p>Sections are kind of special though, in that they don’t actually appear inline <em>per se</em>, because they’re block-level elements (i.e. their own paragraphs) which means they’ll put a paragraph break where they appear. They still replace
their :inline macro link though, just like with variables and functions. When inline-expanding a section, you can still have paragraph breaks, <em>additional</em> <strong>formatting</strong>, and so on. And you can even inline sections
which themselves contain <a title="{#RaiseAlert}" href="javascript:;" data-call-function="RaiseAlert">macros</a>!</p>
</div>
<div id="AboutFormatting" data-tags="" class="section" hidden="true">
<p>Story text is written in Markdown, which means we have access to <em>all kinds</em> of <strong>formatting</strong>, including:</p>
<h1>Headers</h1>
<h2>Sub-headers</h2>
<ul>
<li>Unordered lists (like this one)</li>
<li>Ordered lists (1, 2, 3, 4…)</li>
<li>Links can also <a title="{#RaiseAlert}" href="javascript:;" data-call-function="RaiseAlert"><em>contain</em> <strong>formatting</strong></a></li>
</ul>
<p>Basically, anything Markdown can do, you can do in your story text! You can even inline <span style="color:#ff0000">raw HTML</span> which means you could do video embeds, HTML5 canvas, and all kinds of other fancy stuff.</p>
<p>And of course, because fractive games are ultimately HTML in the end, you can create your own HTML template with whatever layout you want, and style it with CSS. For example, you could surround your game with a header and footer, or create
a sidebar which (along with some custom Javascript) tracks your player’s inventory and stats as they move through the story.</p>
<p><a title="{@LongStories}" href="javascript:;" data-goto-section="LongStories">How does fractive handle long/complicated stories?</a></p>
</div>
<div id="LongStories" data-tags="" class="section" hidden="true">
<p>Fractive’s main goal is to be the best tool for writing complex, dynamic hypertext fiction that has lots of branches and genuinely consequential choices. What you’re reading right now is produced by a <em>very</em> eary version of the tool,
so this goal isn’t fully realized yet, but it is the direction I’m heading.</p>
<p>You can split long story text up into as many individual Markdown files as you like, and they can be named whatever you like. The same goes for game logic in Javascript; you could have separate .js files for each logical class, or for each
scene or major location in your story, or however else you’d like to organize it. When you publish your story, all the files in the story source folder are gathered up automatically, and everything gets compiled together into a single
self-contained HTML file.</p>
<p>In the future I’ll be exploring additional tools and visualizations to help authors understand, trace, and debug the complexity of large, deeply-branching narratives. Those tools and visualizers will likely be the most experimental, and pivotal,
aspects of fractive’s development.</p>
<p>Anything you’d like to review?</p>
<p><a title="{#FunctionLink}" href="javascript:;" data-call-function="FunctionLink">Wh