I’m creating something similar to iffinity currently, and for much the same reasons: I found Twine quite limiting when you get to more than trivial amounts of code, and I had to resort to some hacks to get Sugarcube to do what I want.
I’m approaching this from another direction though: Instead of reinventing the wheel with another build tool (which the iffinity cli is as far as I understand), I’m using normal JS ecosystem tools: The UI is made with Svelte (making reactivity much easier than in Twine) and the code is in Typescript (because I just can’t live without static types).
I even have a Webpack plugin that turns markdown files into Svelte components and a directory of Svelte components or markdown files into a nice import array you can just feed to the engine:
index.ts:
import "if-framework/styles/default.scss";
import { History, Main, define } from "if-framework/choice";
import { Moment, engine } from "if-framework/choice";
// Generated from the passages directory by the Webpack plugin
import passages from "./passages";
// Add the generated passages to the engine.
// For generated passages, the passage name is the file name without the extension.
engine.addPassages(passages);
// Set the starting point with an initial history.
engine.initHistory(new History([new Moment("test", {})], 0));
// Define the custom elements used in Markdown passages.
define();
// Remove the default Javascript warning.
document.getElementById("iff-noscript-container")?.remove();
// Initialize the default UI.
new Main({
target: document.body,
props: {
// Additional components to be displayed in the sidebar can be added here. A Svelte component constructor is expected.
sidebarComponents: [],
// Header and footer components can be added, too.
header: null,
footer: null,
}
});
passages/test.md:
# Hello World!
This is a story.
<iff-link passage="test2">Continue</iff-link>
I could wrap much of the coed in the engine, but for modularity I kept it out. I do want to emphasize modularity, and in order to bridge the gap of creating a new project, I’ll make a project generator (probably using yeoman).
Currently the framework provides the Webpack loaders for generating passages, a history system inspired by Sugarcube, and I’m working on a saving system right now. That is, the saving system works, but currently only the automatic save to session storage after a history change, like Sugarcube does, I’ve jet to finish the saving UI. Another nice thing I got working is a webpack loader that enables you to use markdown at compile time in the Svelte component passages, so you don’t have to ship marked in the final build.
One more complex part I want (and the main reason why I made this in the first place) is a module that helps creating a text-based RPG.
With how nice Svelte can handle reactivity and conditional rendering, I don’t think I’ll need to include many builtin elements.
I’ll make a post of its own for this when I make the code public, but for now here’s the rendered output of the example I gave: