0 votes
asked by (120 points)
I want to make an index sorted by tags that automatically added to itself.  For instance, a list that searches for the titles of all passages with the "monster" tag and adds it to the list.

Bad example: (print: (passage: any )'s name that contains "monster" 's tags)

Is there anything is Harlowe 2.1 like (history: ) that just searches all passages and not just the ones that you've been too?  Is there any equivalent to "story.lookup" that I see in Sugarcube documentation?

1 Answer

0 votes
answered by (131k points)

There is currently no macro for retrieving the collection of Passages within a Story, so you would need to use Javascript to retrieve such a collection.

NOTE: Harlowe currently has no documented Javascript API, and it has been deliberately designed by it's developer to restrict access to the internals of the story format's Javascript engine. The story format also has limited support for using Javascript either directly within a Story, or to extend the core functionality of it's engine.

1. The following Proof of Concepts demonstrate two possible methods that can be used to obtain the list of Passage names you require. Both have their short comings and rely on knowledge gained by looking at the source code of either the meta data generated by the Twine 2 application itself or of the Story Format engine.

2. The source code of both the Twine 2 application and the Harlowe Story Format are subject to change which means that the related Proof of Concept could stop working without notice, so usage of either of the following is left to the Author's discretion.

3. Neither of the following Proof of Concepts has been fully tested, nor do their related Javascript code examples contain all the error catching code that is required to make them proper working examples.

4. Both of the following Proof of Concepts create a Javascript Namespace named GE which is used to separate the custom Javascript code create by me from the web-browser's (or other third-party's) own code so that there are no clashes. I strongly suggest you rename this namespace to something more meaningful to yourself, remembering to also change all other references to that namespace.

The Proof of Concepts:

A. Obtaining the names from the story meta data generated by the Twine 2 application.

The Twine application creates a HTML element structure containing all the Story's Passage meta data and it then embeds that meta data within the generated Story HTML file. The main element of this structure is named tw-storydata and this element contains one-or-more child tw-passagedata elements.

The following Javascript code example creates a function named GE.getNamesOfPassagesWithTag() which uses jQuery to search through that structure looking for all the tw-passagedata elements that have the require tag, it then creates an Array containing the names of the related Passages which it returns. The following code needs to be placed within the Story Javascript area.

/* Create your own personal namespace, I name mine GE. */
window.GE = window.GE || {};

window.GE.getNamesOfPassagesWithTag = function(tag) {
	var tagged = $('tw-storydata tw-passagedata[tags~="' + tag + '"]')
	var names = tagged.map(function () {
		return this.getAttribute('name');
	return names;


B. Obtaining the names via an undocumented feature of the story format engine.

The following Javascript code uses the undocumented getTagged() function of the undocumented Passages module to obtain a collection of undocumented Passage objects that have been assigned the required tag. It then extracts the Passage names of the elements within that collection into an Array which it then returns. The following code needs to be placed within the Story Javascript area.

/* Create your own personal namespace, I name mine GE. */
window.GE = window.GE || {};

window.GE.getNamesOfPassagesWithTag = function(tag) {
	var tagged = Passages.getTagged(tag);
	var names = tagged.map(function (el) {
		return el.get('name');
	return names;


The following example shows how to use the new GE.getNamesOfPassagesWithTag() function (created by both of the above Proof of Concepts) within a Passage, it also demonstrates one way to loop through the content of the returned Array.

(set: $names to GE.getNamesOfPassagesWithTag('abc'))

(for: each _name, ...$names)[\


Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.