fractive
Version:
Fractive is a hypertext authoring tool, primarily intended for the creation of interactive fiction.
737 lines (677 loc) • 103 kB
HTML
<html>
<head>
<title>Fractive User Guide</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta property="og:title" content="Fractive User Guide" />
<meta property="og:description" content="Fractive is a Markdown-based hypertext authoring tool for writing interactive fiction. This interactive user guide explains how to set it up, use it to write stories, build and distribute those stories, and extend Fractive in new and creative ways."
/>
<meta name="twitter:card" content="summary" />
<meta name="twitter:creator" content="@invicticide" />
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"></link>
<style>
:root {
--main-background-color: #FAFAFA;
--main-text-color: #555555;
--sidebar-background-color: rgb(66, 53, 90);
--sidebar-text-color: rgb(30, 25, 41);
--chapter-background-color: rgb(122, 99, 167);
--chapter-text-color: rgb(36, 29, 50);
--topic-background-color: rgb(36, 29, 50);
--topic-text-color: rgb(188, 152, 255);
--code-block-background-color: rgb(19, 18, 20);
--code-block-text-color: #bababa;
--code-inline-background-color: #e9e9e9;
--code-inline-text-color: #ff0000;
--inline-text-color: #bababa;
--link-text-color: rgb(155, 101, 255);
--sidebar-link-text-color: rgb(188, 152, 255);
--link-hover-color: #FF6666;
}
/* ------------------------------------------------------------------------------------
/* Sidebar */
#__sidebarContainer {
position: absolute;
top: 0px;
left: 0px;
width: 300px;
height: 100%;
overflow: auto;
background-color: var(--sidebar-background-color);
}
#__sidebar {
padding: 0px;
}
#__sidebar h1 {
width: calc(100% - 20px);
padding: 10px;
margin: 10px 0px;
background-color: var(--chapter-background-color);
color: var(--chapter-text-color);
font-size: 18pt;
font-weight: bold;
text-transform: uppercase;
}
#__sidebar h2 {
width: calc(100% - 20px);
padding: 5px 10px;
margin: 10px 0px;
background-color: var(--topic-background-color);
color: var(--topic-text-color);
font-size: 15pt;
font-weight: bold;
}
#__sidebar p {
width: calc(100% - 20px);
padding: 0px 10px;
background-color: var(--sidebar-background-color);
color: var(--sidebar-text-color);
font-size: 13pt;
}
#__sidebar a:link,
#__sidebar a:visited {
color: var(--sidebar-link-text-color);
text-decoration: none;
}
#__sidebar a:active,
#__sidebar a:hover {
color: var(--link-hover-color);
text-decoration: none;
}
/* ------------------------------------------------------------------------------------
/* Main section */
#__contentContainer {
position: absolute;
top: 0px;
left: 300px;
width: calc(100% - 300px);
height: 100%;
overflow: auto;
}
#__content {
max-width: 900px;
margin-left: 50px;
margin-right: 50px;
}
#__topNav * {
font-size: 13pt;
font-weight: bold;
}
#__topNav a:link,
#__topNav a:visited {
color: var(--link-text-color);
text-decoration: none;
}
#__topNav a:active,
#__topNav a:hover {
color: var(--link-hover-color);
text-decoration: none;
}
#__currentSection {
color: var(--main-text-color);
}
.__inlineMacro {
color: var(--inline-text-color);
}
h1 {
font-family: Arial, Helvetica, sans-serif;
font-size: 32pt;
margin-top: 28pt;
margin-bottom: 0pt;
}
h2 {
font-family: Arial, Helvetica, sans-serif;
font-size: 22pt;
margin-top: 28pt;
margin-bottom: 0pt;
font-weight: bold;
}
h3 {
font-family: Arial, Helvetica, sans-serif;
font-size: 18pt;
margin-top: 28pt;
margin-bottom: 0pt;
font-weight: bold;
}
body {
background-color: var(--main-background-color);
}
p {
font-family: Arial, Helvetica, sans-serif;
font-size: 16pt;
line-height: 1.5em;
}
a:link,
a:visited {
color: var(--link-text-color);
}
a:active,
a:hover {
color: var(--link-hover-color);
}
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 {
background-color: var(--code-block-background-color);
padding: 10px 20px;
max-height: 600px;
white-space: pre-wrap;
overflow-y: auto;
}
pre code {
line-height: 1.25em;
font-family: "Courier New", "Courier", monospace;
font-size: 14pt;
font-weight: bold;
background-color: var(--code-block-background-color);
color: var(--code-block-text-color);
}
code {
font-family: "Courier New", "Courier", monospace;
font-size: 12pt;
padding: 4px;
border-radius: 6px;
background-color: var(--code-inline-background-color);
color: var(--code-inline-text-color);
}
img {
margin: 20px 0px;
}
hr {
border: 0;
height: 1px;
background-image: linear-gradient(var(--main-text-color), var(--main-text-color));
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
Core.AddEventListener("OnBeginStory", () => {
// Populate the sidebar from the @TableOfContents section so it's easy to maintain
var sidebar = document.getElementById("__sidebar");
var toc = Core.GetSection("TableOfContents");
Core.ActivateElement(toc);
sidebar.appendChild(toc);
});
Core.AddEventListener("OnGotoSection", function(id, element, tags, reason) {
// Scroll to top of new content
var contentDiv = document.getElementById("__contentContainer");
if (contentDiv) {
contentDiv.scrollTop = 0;
}
});
function InlineFunc() {
return "Hello, world!";
}
</script>
</head>
<body>
<div id="__history" hidden>
<!-- History is included so we can have a functional back button, but we never actually show it directly -->
</div>
<div id="__sidebarContainer">
<div id="__sidebar">
<!-- Sidebar table of contents is dynamically populated from script at init time -->
</div>
</div>
<div id="__contentContainer">
<div id="__content">
<!-- source/introduction.md -->
<div id="QuickStart" data-tags="" class="section" hidden="true">
<h1>Quick start</h1>
<p><a title="" href="javascript:;" data-replace-with="@QuickStart-Installation" id="inline-0"><strong>If you haven’t installed Fractive yet, click here</strong> <i class="fa fa-info-circle" aria-hidden="true"></i></a></p>
<p>Create a new story project:</p>
<pre><code>fractive create path/to/my/story
</code></pre>
<p>Launch your favorite code editor – I particularly like <a title="" target="_blank" href="https://code.visualstudio.com">VS Code <i class="fa fa-external-link" aria-hidden="true"></i></a> – and open the default story text file, <code>source/text.md</code>.
You’ll see the following:</p>
<pre><code>{{Start}}
Your story begins here.
</code></pre>
<p><code>{{Start}}</code> marks the beginning of a new <strong>section</strong>, called “Start”. Your story will contain many sections, each of which must be named uniquely. The “Start” section is the one your story will start on when it’s
first launched.</p>
<p>Add a second section:</p>
<pre><code>{{Elsewhere}}
This is a different section.
</code></pre>
<p>Now add a link to the second section from the first section. Story text is written in <a title="" target="_blank" href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet">Markdown <i class="fa fa-external-link" aria-hidden="true"></i></a>,
so you can use Markdown link syntax:</p>
<pre><code>{{Start}}
Your story begins here.
[Go elsewhere]({@Elsewhere})
</code></pre>
<p>The link URL <code>{@Elsewhere}</code> is a <strong>macro</strong> pointing to the section called “Elsewhere”. Macros are enclosed in <code>{}</code> and have a leading <strong>metacharacter</strong> indicating the macro’s type. In this
case we used <code>@</code> which indicates a section macro; clicking this link will take the player to the named section.</p>
<p>Build the story project:</p>
<pre><code>fractive compile path/to/my/story
</code></pre>
<p>Navigate to <code>path/to/my/story/build</code> and open up the <code>index.html</code> in a web browser to run your story!</p>
<p>You now know enough to create interactive fiction stories both simple and complex. However, Fractive is capable of much more than this! You can browse the built-in examples to see other features by doing:</p>
<pre><code>fractive examples
</code></pre>
<p>Each folder in <code>examples</code> is its own Fractive <strong>project</strong>, which you’ll learn about in the next section.</p>
<p><a title="" href="javascript:;" data-goto-section="Projects-Intro"><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> Next: Projects</a></p>
</div>
<div id="QuickStart-Installation" data-tags="" class="section" hidden="true">
<p>Fractive is built on <a title="" target="_blank" href="https://nodejs.org">Node.js <i class="fa fa-external-link" aria-hidden="true"></i></a>, so you’ll need to install that if you don’t already have it. (Fractive currently targets
version 8.9.0 LTS.)</p>
<p>Once Node.js is installed, open a command line and install Fractive:</p>
<pre><code>npm install -g fractive
</code></pre>
<p>Fractive is now globally available on the command line. Type <code>fractive</code> to see usage instructions.</p>
</div>
<!-- source/projects.md -->
<div id="Projects-Intro" data-tags="" class="section" hidden="true">
<h1>About projects</h1>
<p>Story text is written in Markdown (.md) files, and game logic is written in Javascript (.js) files. These files, plus any additional assets (images, etc.) are kept together in a Fractive <strong>project</strong>. You can create a new project
like this:</p>
<pre><code>fractive create path/to/my/story
</code></pre>
<p>In the new project folder you’ll see this default structure:</p>
<pre><code>story
|- assets/
|- source/
|- fractive.json
|- template.html
</code></pre>
<p>The <code>source</code> folder contains all your Markdown (.md) and Javascript (.js) files.</p>
<p>The <code>assets</code> folder contains images, video clips, and other miscellaneous assets. Not all projects will require these.</p>
<p>The <code>template.html</code> is a formatting template for how your published story will look in the browser. See <a title="" href="javascript:;" data-goto-section="Stories-Templates">Templates</a> for details.</p>
<p>Finally, the <code>fractive.json</code> is your <strong>project file</strong>. It contains all your project settings, like rules for where to find source files and where builds should go. If you take a peek inside, you’ll see the default
rules:</p>
<pre><code>markdown: [ "source/**/*.md" ],
javascript: [ "source/**/*.js" ],
assets: [ "assets/**" ],
ignore: [],
template: "template.html",
output: "build",
</code></pre>
<p><a title="" href="javascript:;" data-goto-section="Projects-Configuration"><i class="fa fa-arrow-circle-right" aria-hidden="true"></i> Next: Project configuration</a></p>
</div>
<div id="Projects-Configuration" data-tags="" class="section" hidden="true">
<h1>Project configuration</h1>
<p>This page lists all the configuration options available in the <code>fractive.json</code> project file.</p>
<h1>Project metadata</h1>
<p>Aside from the title, none of the project metadata is currently used, but in the future it will be displayed to the player (e.g. on a standardized title page, in an online database of Fractive stories, etc.)</p>
<pre><code>"title": "My Project Title"
</code></pre>
<p>Specifies the name of your story. This will be shown to the player, so it should be your actual story title, not a project code name or internal name. This will also appear as the title in any OpenGraph card when this game is linked to
on social media. The page title will also be set to this if the <code><!--{title}--></code> mark is present in your template; see <a title="" href="javascript:;" data-goto-section="Stories-Templates">Templates</a> for details.</p>
<pre><code>"author": "Your Name"
</code></pre>
<p>Specifies who wrote the story. This could be your real name, an online nickname, a social media handle, or even a company name.</p>
<pre><code>"description": "About your story"
</code></pre>
<p>Give a brief (one or two sentences) description of your story. This will also appear as the description in any OpenGraph card when this game is linked to on social media.</p>
<pre><code>"website": "Your website"
</code></pre>
<p>Give an online address where players can learn more about you, find more of your stories, etc. This could be your website URL, a social media handle, or even an email address. You can also just leave it blank if you prefer.</p>
<h2>twitter</h2>
<pre><code>"twitter": "@yourname"
</code></pre>
<p>If you specify your Twitter handle here, it will be linked in OpenGraph cards when this game is linked to on Twitter.</p>
<h1>File paths</h1>
<p>These options specify where in your project folder Fractive should look for different kinds of files, what should be included in a build, and what should be ignored.</p>
<p>These are generally <a title="" target="_blank" href="https://github.com/isaacs/node-glob#glob-primer">globs <i class="fa fa-external-link" aria-hidden="true"></i></a> or lists of globs.</p>
<p><a title="" href="javascript:;" data-replace-with="@Projects-Configuration-Globs" id="inline-1">How do globs work? <i class="fa fa-info-circle" aria-hidden="true"></i></a></p>
<p>Paths are relative to the <code>fractive.json</code> project file.</p>
<pre><code>"markdown": [
"source/**/*.md"
]
</code></pre>
<p>List of globs indicating where story text (Markdown) fil