invicticide / fractive Goto Github PK
View Code? Open in Web Editor NEWFractive is a free, open-source, Markdown-based hypertext authoring tool for writing interactive fiction.
Home Page: http://fractive.io
License: Other
Fractive is a free, open-source, Markdown-based hypertext authoring tool for writing interactive fiction.
Home Page: http://fractive.io
License: Other
The output html currently includes loads of whitespace and line breaks. It seems worth it to minify it just before we write it to disk.
This would happen at the end of Compiler.Compile()
Can be done at https://github.com/invicticide/fractive/community
With projects of a certain size, it will be necessary to allow disambiguation between duplicate section names. This could be handled automatically by making each source file a namespace, or they could be organized by subfolders, or they could be defined manually somehow.
Maybe namespaces are organized by file automatically, but are invisible until disambiguation is necessary. For example, a link to section {@Section3}
will automatically direct to {{Section3}}
declared in a different file, unless {{Section3}}
is declared in the current file, in which case the local instance takes precedence. To disambiguate, we could use the syntax {@otherfile/Section3}
.
Eventually Fractive is going to need a back button like Twine has.
I can imagine two different ways of implementing this:
It might be worth implementing both and letting users choose between them by calling a Core function or even setting a flag in fractive.json
. Because I can think of situations where Twine's behavior was annoying, but also situations where it would be preferable.
For the first method, we would need to maintain a stack of section id's that have been visited. The back button will call Core.GotoSection()
to return to the beginning of the section at the top of the stack.
For the second method, we could utilize the __history
div to copy over the state of the previous section exactly as it was.
Similar to my proposal for #9's external link icon being defined as raw HTML in fractive.json
, I think the same method could be used to let the user make the back button look however they want. Its position would be definable in template.html in the same way the __currentSection
and __history
divs are.
Function and variable macros are currently expanded like this in Core.ts:
case '#':
{
// Return the result of the named function call
let functionName = macro.substring(1);
let fn = window[functionName];
if(typeof fn === "function") { result = fn(); }
else { console.log(functionName + " is not a function"); }
break;
}
case '$':
{
// Return the value of the named variable
result = window[macro.substring(1)];
break;
}
This restricts Fractive's access only to variables and functions in the global scope. Properties and functions of objects cannot be accessed, but the code could be modified to allow this:
.
as a delimiter.
's are there.The code is really messy for handling macros, and the more functionality we want to add, it's going to end up like Twine with its bizarreness. I'm going to advocate that instead of continuing to write our own macro handling, we implement Liquid.
This implementation would be done through liquid-node and liquid.js. I've done some tests and think this would be viable and yield the following advantages:
if
, else
, unless
, for
, etc. inside of text filescall
for functions instead of #
section
for sections instead of {{ }}I've created a branch in my fork to get working on this. @invicticide I want to know what you think before I go much further with it, but I think this would be huge for extensibility in Fractive and make larger projects like Space Bard more sane.
My thinking is that it's easier to catch bugs when they announce themselves loudly, i.e. in the middle of your hypertext, with an explanation of why. Maybe even in red. :P
The current default templates/basic.html
is bad. I do like having a basic template that has virtually no formatting -- it's useful as both a learning tool and a stripped-down test case -- but the side-by-side history thing feels real clunky. This template should be redesigned a bit to feel more like a nice "minimal" template but still as something someone might actually want to use.
I'd also like to ship MVP with a second template that's a little bit more designed. Minimal is great for testing and stuff, but it'd be nice to have an alternative that's a bit more publication-ready: nicer color scheme, font choice, whitespace layout, etc. Just something more appealing.
I’m thinking of accepting an (optional) json file that might look something like:
{
title: "My Game",
author: "invicticide",
website: "www.my-website.com",
twitter: "@invicticide",
// ...
input: {
// glob syntax, like .gitignore
markdown: "./markdown/**",
// Any of these source entries could alternately be arrays, so you can specify multiple source paths/patterns
javascript: [
"./main.js", // You could explicitly target individual files first, maybe because they declare global dependencies
"./scripts/**", // Entries can be files, folders, or globs
],
// Stuff that doesn't get processed, just copied to the destination
misc: "./misc/**"
},
output: "./dist",
options: {
// If true, embed bundled scripts at the top of the html like we've been doing
// If false, deploy bundled scripts as a concatenated bundle.js-like alongside the html
embedScripts: true,
// ...
}
}
If the json isn't present, the default behavior is like we currently have it, where it just grabs up all the .md and .js files it finds in the destination folder (recursively), except that I might make also it output to a dist
folder by default instead of dumping everything alongside your source content. Point being, you don't have to create a build config json, but you can, and it gives you more flexibility, especially for dealing with complex projects which have extensions.
Write reference documentation in Fractive and automatically build it along with examples. This serves a few purposes:
The docs project lives in a new docs/source
folder and its build output is just docs/index.html
for easy access.
The readme.md
should be streamlined to just install instructions and a pointer to the docs. Most of the current readme contents can be moved verbatim (or nearly verbatim) into the docs.
Put a macro in link text.
Having macros in link text and link tags could be nice.
For normal links this is no big deal because the target url appears in the browser's status bar.
For macro links this sucks because they just have href=#
since their click is handled in Javascript. From a player perspective, nobody cares, but from a dev perspective it'd be nice to be able to see the actual macro being linked to.
If we just set href={@someSection}
the userAgent will probably try to resolve the href
on click, which is no bueno. Instead, we can set alt={@someSection}
and/or title={@someSection}
so the macro target appears in a tooltip.
This might also be worth hiding behind some debug flag in the build configuration that doesn't exist yet, so it's omitted from "release" builds.
In the doc
project, code blocks with long lines don't wrap to their containers.
The Fractive NPM package is currently out-of-date, but there are outstanding questions that need to be resolved regarding how that package is structured, published, and integrated into other projects... or if it even makes sense to continue maintaining it as such at all.
In the future I see Fractive becoming an executable application (probably inside an Electron wrapper) that functions as a story IDE. For most users, you'd just download the application and run it. Is there still a reasonable use case (e.g. for advanced extensions/integrations) to have an NPM package for which users would bypass the "official" application and just do npm install fractive
as a dependency for some larger project? If so, what does that really need to look like?
In Twine, a link to another section can be written simply, as [[other section]]
if the section being linked to is named the same as the link text. Maybe we could implement the same syntax as a shorthand for that situation, or something like [Link]({@})
for internal consistency, but that's more awkward.
Project configs contain metadata (title, author, etc.) which is currently unused. These should be surfaced into a title page which is displayed initially when opening a new story.
The title page div should be placed near the top of the template, so it loads first and can be rendered ASAP. The title page contains a loading spinner graphic. Core registers an onload
such that when the rest of the Fractive story and its dependencies (images, etc.) are all fully loaded, then the loading spinner in the title div is replaced with a "start" link which invokes a Core.GotoSection("Start")
to start the game.
Use webpack instead of manually gathering and concatenating all the source files?
Can be done at https://github.com/invicticide/fractive/community
When compiling Markdown files, Fractive is inserting a <br>
element for every newline in the Markdown file. Here's the proper way to handle newlines.
Currently the output html is built from a hardcoded string in Compiler.Compile() which has the rendered story text and scripts embedded into it. This is super inefficient and ugly and hard to customize.
Instead, we should use a template html file with some special macros in it for where to embed the scripts and story text. Maybe something like this:
<html>
<head>
<script type="text/javascript">{{script}}</script>
</head>
<body>
{{story}}
<div id="__history"></div>
<hr/>
<div id="__currentSection"></div>
</body>
</html>```
We should be able to pass a desired template to the compiler, which allows for easy end-user customization.
Right now a new story project requires an annoying amount of manual setup:
Create a section containing an inline link (i.e. one using the :inline
specifier), a link to a second section, and a functional "back" link. Build and run the story. Do not click the inline link at this time; just navigate directly to the second section. Then click "back" to return to the first section. Now click the inline link.
Result: the inline link expands in-place as expected, but another copy of the inline link also appears, which can be expanded again into a second copy of the content.
The first paragraph of a section I wrote wasn't appearing. I realized it was because I didn't skip a line below the section declaration.
Make a text.md
like this:
{{Start}}
What about me, huh?
You wouldn't know it, but I am actually the second paragraph.
Compile and run.
These two section declarations should both be equivalent:
{{Start}}
First paragraph.
and
{{Start}}
First paragraph.
The examples folder should be built by the story compiler to catch any issues with the compiler. If any occur, it should fail the overall build. This way, examples can also be used as a form of unit test.
May be worth creating a separate tests folder for more granular tests as well, and running it through the same process.
I can't get Fractive to render a backslash.
Build the examples in my link tags branch here. Backslashes won't render at all. I tried writing them in Markdown first as one backslash (\
) then as an escaped backslash (\\
) then in a last-ditch effort, a triple backslash (\\\
) and surprisingly, none of these threw an error, and none of them rendered a backslash.
In the example, I need to be able to share JSON with backslashes in it.
When passing a folder to the compiler, it only finds files in the root of that folder. It should recurse subfolders so authors can organize their story text and scripts however they'd like.
This would need to happen near the top of Compiler.Compile() where we're gathering the target file lists.
When running fractive from the command line via a global npm installation, it becomes very difficult to reference one of the example templates in an original story without copying the file to a new location relative to the story, not the fractive installation.
I'm thinking we could implement a hackish macro for that like letting the user write the path $(builtin)/basic.html
in fractive.json
and Compiler.ts would interpret that into the path of the fractive installation.
A file system error on Windows when putting assets inside nested folders in the Assets directory.
Make a new story. Create a folder inside the assets directory, and put another file in there. Then compile.
All folders inside the assets folder should be copied into the output location. Instead, they cause an error.
Many static site generators like Jekyll (which I use for my website) have an option at buildtime to host the output website on some port for you to see the results quickly:
jekyll serve path/to/site
Additionally, Jekyll provides an option --watch
which auto-regenerates the site when the source files change. These two features would make iteration on story files an absolute dream.
Running the basic example in Firefox on Windows, the section demonstrating inline macros has some funky behavior. When you click one of the links that expands, the page scrolls all the way back to the top, so you can't see the transformation. You have to scroll back down to see the new text.
Run the basic example in Firefox (or potentially another browser) and mess around with inline links.
The page's scroll position shouldn't change when clicking inline links.
When a section is moved into history, its hyperlinks remain active. This is super bad news for coherent story flow. Those links should be disabled.
(There's probably a related class of issues for certain media embeds and junk like that, too.)
Sometimes story text compilation errors will either report no sourcepos at all, a sourcepos of (0,0), or a sourcepos that looks correct but turns out to be inaccurate.
I haven't done much investigation of this yet but what I've seen so far suggests Commonmark isn't always setting the sourcepos so it may actually be their bug, not ours...? More research is needed.
Macros are currently expanded regardless of context, so trying to do something like this:
This is some story text which would like to tell you that macros look like this: `{#Function}`
will just expand the macro, even though it's enclosed in backticks. Code blocks (backticks and indents) should suppress this behavior.
Need to add this context awareness to Core.ExpandSection().
Twine lets developers tag every passage with arbitrary strings that can be used for sorting/processing and even exported for wrappers like UnityTwine. An example of this coming in handy is Ben Wander's A Case of Distrust:
I use Twine’s Tags feature to determine what images (characters, locations, etc) my game should be showing. For example, if we’re in a Passage that is marked with the “Butler” Tag, my code will show the butler image. If we’re in a Passage that’s marked with the “Malone’s Apartment” Tag, my code will show Malone’s apartment.
A similar system might be ideal for me in Space Bard, to mark sections with info such as which character is speaking, what portrait to use, etc.
I want to be able to tag sections with a simple extension of the current syntax, i.e. {{SomeSection: tag1, tag2}}
. Then some functions added to Core
would be nice:
Core.GetTags(sectionName)
Core.GetSectionsWithTag(tag)
Core.GetCurrentSectionTags()
Feel free to assign me this one.
Since we're writing the engine in TypeScript it only makes sense that someone might want to write their story scripts in some other dialect of JavaScript. fractive.json
should optionally specify the command for a transpiler, and Compiler.ts can run that command on every story script given in the glob expressions before bundling/copying them into the output folder.
A language config file should be used to define separate directories for markdown files in different languages. The compiler can output multiple localized index.html files.
Guess who has two thumbs and is happy to implement this? XD
Links that go to some offsite address (as opposed to a Fractive macro destination) should open in a new window/tab, and should display a little "offsite" icon after the link, like you'd see on Wikipedia or whatever.
Might also want to control this on a per-story basis in a settings.json or something.
I can imagine scenarios where I want to generate a list of links at runtime depending on runtime variables. Right now I'd have to generate my own <a>
tags, set the data attributes I want, and also call RegisterLinks(), right?
It might be nice to create links with some function like, Core.GenerateLink(linkText, linkDestination)
that could compile macros and/or markdown in the link text, and macros in the link destination.
For a concrete example of how this would be useful, I might want to generate a table of contents at runtime.
Wrapping an image in a link gives a text link with the label being the image's alt text, rather than rendering the image itself.
[![Image alt text](image.png)](foo.com)
Renders the text Image alt text
instead of the image image.png
.
The image.png
should appear, with its alt
and title
tags set to Image alt text
, and it should link to foo.com
when clicked.
Right now it's kind of cumbersome to run the compiler:
node lib/Compiler.js path/to/story/
It'd be nicer to be able to just do something like:
build path/to/story/
This would require creating platform-specific scripts (bat/command/sh) that wrap up the compile command.
Just discovered a gotcha: I had been working for Selfcare Jam without putting my story in a repo. Once I moved it into a repo, README.md in the root directory where I had put everything else, started throwing off the Compiler. Maybe we should just ignore files like README.md, code of conduct, etc?
Also: node_modules directories, .git, etc.
Maybe a .fractignore file would be a better general solution?
Currently when the browser back button is pressed it will navigate the player away from the Fractive story and lose the entire story state. This could suck if you're a ways into a story and press the browser back button with intent to back up one section.
It's not acceptable to override the browser back button's behavior (e.g. to prevent leaving the page) but we do see a common convention of catching it and popping a warning or confirmation dialog. That would be good to have here.
I made changes to the library, and ran npm install -g ./
to update my Fractive installation. However, the Javascript files hadn't changed, so the old library code was still executing. It seems like that command should also run the build process before updating the install.
Every time I go to call a function and embed the output in a section, I forget whether or not I'm supposed to declare the macro with :inline
or not. A specific error message would be nice, because currently what happens if you do the wrong thing (:inline
), is you get targetFunction is undefined
, which is confusing when you know you've defined the function.
an optional argument should be the path at which to export.
Load up the basic example and navigate to the section which demonstrates inline links. Expand the function, variable, and section inlines. Note that all three inlines appear in brown so they stand out from the rest of the text.
Now click "back" in the header bar and observe the three expanded inlines. The function and variable are both brown as before, but the section is displayed in black like normal text.
C:\Users\Nathaniel\fractive-story-template\fractive>npm install
> [email protected] prepare C:\Users\Nathaniel\fractive-story-template\fractive
> npm run build
> [email protected] build C:\Users\Nathaniel\fractive-story-template\fractive
> ./node_modules/typescript/bin/tsc
'.' is not recognized as an internal or external command,
operable program or batch file.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `./node_modules/typescript/bin/tsc`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional log
ging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Nathaniel\AppData\Roaming\npm-cache\_logs\2017-11-06T22_05
_47_358Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] prepare: `npm run build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] prepare script.
npm ERR! This is probably not a problem with npm. There is likely additional log
ging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Nathaniel\AppData\Roaming\npm-cache\_logs\2017-11-06T22_05
_47_447Z-debug.log
I keep typing Core.GoToSection
and not Core.GotoSection
. I want to say this is one of those ridiculous things that doesn't matter, but sometimes it's really hard to figure out what's wrong. Can we at least get an alias for it so the typo is supported?
Another expansion that could be made simultaneously, is a convenience function for going to the same section you're currently viewing, as a way of refreshing it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.