The Extwee project is both a Twee compiler (Twee -> HTML) and a HTML decompiler (HTML -> Twee). This means that it can take a Twine 2-compatible HTML file and create a Twee file from its contents, converting the elements back into textual passages. Working within this process, a Story object and its into Passage objects can be examined.
Creating a Project Directory
Create a new directory. From the command-line, run the following
npm init
Assume the defaults or otherwise change them as needed.
Next, as Extwee is on NPM, install that module.
npm i extwee
Once the dependencies have been installed, create a new file “index.js”
Loading Extwee’s Objects
Once the Extwee module has been downloaded, its objects can be used in a project. Looking at the “index.js” file of Extwee on GitHub, its model can be taken and changed slightly to meet the new needs of only decompiling a HTML file.
const FileReader = require('extwee/FileReader.js');
const TweeWriter = require('extwee/TweeWriter.js');
const HTMLParser = require('extwee/HTMLParser.js');
The same is true of the decompiling process. However, as argv is not part of this project, it can be ignored. Instead, some local variables can be added for testing purposes.
let input = "HTMLExample.html";
let output = "testing.twee";
let fr = new FileReader(input);
let hd = new HTMLParser(fr.contents);
let tw = new TweeWriter(hd.story, output);
Reading a Story
As the “Story.js” file of Extwee shows on GitHub, a Story object has an internal array property of passages. Instead of passing the Story object to TweeWriter, then, it can be used to read through a Twine Story.
Looking at the “Passage.js” file of Extwee on GitHub shows that each Passage of a Story object has its own internal property called text that contains its text.
Knowing these two pieces of information, the last line where TweeWriter was used can be changed to move through the passages of a Story object and, as an initial test, print the text of each Passage it encounters.
for(let p of hd.story.passages) {
console.log(p.text);
}
Counting Words
A quick example that read through each Passage of a Story counted the total number of words might look like the following:
const FileReader = require('extwee/FileReader.js');
const TweeWriter = require('extwee/TweeWriter.js');
const HTMLParser = require('extwee/HTMLParser.js');
let input = "HTMLExample.html";
let output = "testing.twee";
let fr = new FileReader(input);
let hd = new HTMLParser(fr.contents);
let totalWords = 0;
for(let p of hd.story.passages) {
totalWords += p.text.length;
}
console.log("Total words is " + totalWords);
Counting Basic Links
To only count (and not record) the number of basic links in a Twine 2-compatible HTML file, the code might look like the following:
const FileReader = require('extwee/FileReader.js');
const TweeWriter = require('extwee/TweeWriter.js');
const HTMLParser = require('extwee/HTMLParser.js');
let input = "HTMLExample.html";
let output = "testing.twee";
let fr = new FileReader(input);
let hd = new HTMLParser(fr.contents);
let linkCount = 0;
for(let p of hd.story.passages) {
let links = p.text.match(/\[\[.*\]\]/g);
if(links != null) {
linkCount++;
}
}
console.log("Total basic links are " + linkCount);
Reading Metadata (StoryData)
In the Twee 3 specification, the StoryData passage holds information about the story itself. To read this, look for a passage named “StoryData”. As it is JSON-encoded values, it can also be parsed back into an object.
const FileReader = require('extwee/FileReader.js');
const TweeWriter = require('extwee/TweeWriter.js');
const HTMLParser = require('extwee/HTMLParser.js');
let input = "HTMLExample.html";
let output = "testing.twee";
let fr = new FileReader(input);
let hd = new HTMLParser(fr.contents);
let metadata = {};
for(let p of hd.story.passages) {
if(p.name == "StoryData") {
metadata = JSON.parse(p.text)
}
}
console.log(metadata);