<center><h1>twineNotes</h1></center><<set _noteNum to NaN>>\
<h2>Twine</h2>\
This page provides custom <a href="https://www.motoslave.net/sugarcube/2/docs/#macros-macro-widget" target="_blank">widget</a> code for the <a href="https://www.motoslave.net/sugarcube/2/" target="_blank">Sugarcube</a> format of <a href="https://twinery.org/" target="_blank">Twine</a>. If you don't know what that means, this page probably won't be of much interest to you, but I recommend checking out <a href="https://twinery.org/" target="_blank">Twine</a> nonetheless! It's an easy-to-learn tool for making interactive fiction, games, and non-linear stories, it's free and open-source, and it can be downloaded or used online!
<h2>On This Page</h2>\
*Twine
*What is twineNotes?
*Code
*Usage
*Expanded Code with Comment Explanations
*Expanded Code, without Comments
*Notes Lite
<h2>What is twineNotes?</h2>\
twineNotes is a set of two interconnected <a href="https://www.motoslave.net/sugarcube/2/" target="_blank">Sugarcube</a> <a href="https://www.motoslave.net/sugarcube/2/docs/#macros-macro-widget" target="_blank">widgets</a> that provide an easy way to create superscripted messages which can be opened and collapsed repeatedly, known as "notes".<<note "Lorem ipsum!" "Example">> The widget is highly customizable, allowing for one to specify not only the note's text but also the text for opening and collapsing the note, as well as offering four different options for how the note is collapsed. All of these aspects are optional, and can be left out of the specifications to set them to their default values.
<h2>Code</h2>\
To use twineNotes, one must simply copy-paste the following code into the <a href="https://www.motoslave.net/sugarcube/2/docs/#code-tag-widget" target="_blank">widget passage</a> of their chosen story. When the code is expanded, a single whitespace is generated before the note, and as such, the condensed version is to be considered the official version of twineNotes.
><pre style="white-space: pre-wrap; "><nowiki><<widget "note">><<if ndef _noteNum or typeof _noteNum !== "number" or isNaN(_noteNum) is true>><<set _noteNum to 0>><<else>><<set _noteNum++>><</if>><<if def _args[0] and _args[0] is not 0>><<set _note to _args[0]>><<elseif def _noteDefault>><<set _note to _noteDefault>><<elseif def $noteDefault>><<set _note to $noteDefault>><<else>><<set _note to "No note provided.">><</if>><<if def _args[1] and !(["", 0].includes(_args[1]))>><<set _noteName to _args[1]>><<elseif def _noteNameDefault>><<set _noteName to _noteNameDefault>><<elseif def $noteNameDefault>><<set _noteName to $noteNameDefault>><<else>><<set _noteName to "Note">><</if>><<if def _args[2] and !(["", 0].includes(_args[2]))>><<set _collapseNote to _args[2]>><<elseif def _collapseNoteDefault>><<set _collapseNote to _collapseNoteDefault>><<elseif def $collapseNoteDefault>><<set _collapseNote to $collapseNoteDefault>><<else>><<set _collapseNote to "Collapse Note">><</if>><<if def _args[3]>><<set _collapseMode to _args[3]>><<elseif def _collapseModeDefault>><<set _collapseMode to _collapseModeDefault>><<elseif def $collapseModeDefault>><<set _collapseMode to $collapseModeDefault>><<else>><<set _collapseMode to 0>><</if>><<capture _noteNum, _note, _noteName, _collapseNote, _collapseMode>><span @id="'note' + _noteNum"><<noteText>></span><</capture>><</widget>>
<<widget "noteText">><<link `"^^_noteName^^"`>><<replace `"#note" + _noteNum`>><<if _collapseMode is not 2>><<if _collapseMode is 1>><<link `"^^_collapseNote^^"`>><<replace `"#note" + _noteNum`>><<noteText>><</replace>><</link>> <</if>>^^_note^^ <<if !([1,3].includes(_collapseMode))>><<link `"^^_collapseNote^^"`>><<replace `"#note" + _noteNum`>><<noteText>><</replace>><</link>><</if>><<else>><<link `"^^_note^^"`>><<replace `"#note" + _noteNum`>><<noteText>><</replace>><</link>><</if>><</replace>><</link>><</widget>></nowiki></pre>
<h2>Usage</h2>\
The "noteText" widget is purely internal, and is not for usage in passages. To create a note, simply write """"<<note>>"""" with the note's message as an argument, like so:
>''Input:'' """This is text.<<note "This is a note.">>"""
>''Output:'' This is text.<<note "This is a note.">>
To change the text for opening the note, add a second argument.
>''Input:'' """This is text.<<note "This is a note." "Open me!">>"""
>''Output:'' This is text.<<note "This is a note." "Open me!">>
To change the text for collapsing the note, add a third argument.
>''Input:'' """This is text.<<note "This is a note." "Open me!" "Collapse me?">>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" "Collapse me?">>
To set the open message to the default value when using a custom close message, one may type "Note", or type 0<<note "The zero must not have quotes around it.">>, or simply type a pair of adjacent double-quotes, like so: "".
>''Input:'' """This is text.<<note "This is a note." "" "Collapse me?">>"""
>''Output:'' This is text.<<note "This is a note." "" "Collapse me?">>
\
>''Input:'' """This is text.<<note "This is a note." 0 "Collapse me?">>"""
>''Output:'' This is text.<<note "This is a note." 0 "Collapse me?">>
\
>''Input:'' """This is text.<<note "This is a note." "0" "Collapse me?">>"""
>''Output:'' This is text.<<note "This is a note." "0" "Collapse me?">>
The final argument is the collapse-mode. The default value is 0, in which the "Collapse Note" text appears to the right of the note's message. When the value is set to 1, the "Collapse Note" text appears to the left of the note's message instead. A value of 2 will remove the "Collapse Note" text entirely, instead making it such that one must click the note's message to collapse the note. The final value, 3, makes it so that the note cannot be collapsed once opened. Any other input for this argument will function the same as inputting nothing or 0.
>''Input:'' """This is text.<<note "This is a note." "Open me!" "Collapse me?" 0>>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" "Collapse me?" 0>>
\
>''Input:'' """This is text.<<note "This is a note." "Open me!" "Collapse me?" 1>>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" "Collapse me?" 1>>
\
>''Input:'' """This is text.<<note "This is a note." "Open me!" "Collapse me?" 2>>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" "Collapse me?" 2>>
\
>''Input:'' """This is text.<<note "This is a note." "Open me!" "Collapse me?" 3>>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" "Collapse me?" 3>>
To set the collapse message to the default value when using a non-default collapse-mode, one may type "Collapse Note", or type 0<<note "The zero must not have quotes around it.">>, or simply type a pair of adjacent double-quotes, like so: "".
>''Input:'' """This is text.<<note "This is a note." "Open me!" "" 1>>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" "" 1>>
\
>''Input:'' """This is text.<<note "This is a note." "Open me!" 0 1>>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" 0 1>>
\
>''Input:'' """This is text.<<note "This is a note." 0 0 1>>"""
>''Output:'' This is text.<<note "This is a note." 0 0 1>>
Additional arguments have no impact on the final result. In the case of no arguments, default text is generated.
>''Input:'' """This is text.<<note "This is a note." "Open me!" "Collapse me?" 0 "Lorem" "Ipsum">>"""
>''Output:'' This is text.<<note "This is a note." "Open me!" "Collapse me?" 0 "Lorem" "Ipsum">>
\
>''Input:'' """This is text.<<note>>"""
>''Output:'' This is text.<<note>>
One may also set the variables """"$noteDefault", "$noteNameDefault", "$collapseNoteDefault", and "$collapseModeDefault"""", which will change the default text for each argument. """"_noteDefault", "_noteNameDefault", "_collapseNoteDefault", and "_collapseModeDefault"""" may also be set, which take precedence over the respective story variables.
>''Input:'' """<<set $noteDefault to "Hello!">> This is text.<<note>>"""
>''Output:'' <<set $noteDefault to "Hello!">> This is text.<<note>><<unset $noteDefault>>
<h2>Expanded Code with Comment Explanations</h2>\
><pre style="white-space: pre-wrap; "><nowiki>/*Variable List*/
/*_noteNum: A unique zero-indexed number assigned to each note per passage. Not interacted with by programmer. */
/*_note, _args[0]: The message contained in the note. Programmer inputs _args[0].*/
/*_noteName, _args[1]: The "open note" text. Programmer inputs _args[1].*/
/*_collapseNote, _args[2]: The "collapse note" text. Programmer inputs _args[2].*/
/*_collapseMode, _args[3]: Determines the manner in which the collapse note option is presented. Programmer inputs _args[3].*/
/*_noteDefault, $noteDefault: A programmer-set default value for the _note variable.*/
/*_noteNameDefault, $noteNameDefault: A programmer-set default value for the _noteName variable.*/
/*_collapseNoteDefault, $collapseNoteDefault: A programmer-set default value for the _collapseNote variable.*/
/*_collapseModeDefault, $collapseModeDefault: A programmer-set default value for the _collapseMode variable.*/
/*End of Variable List*/
/*The <<note>> widget is what the programmer will call and interact with to establish the details of a specific note.*/
<<widget "note">>
/*If _noteNum has not been defined, it can be assumed that this is the first note encountered, and as such _noteNum is set to zero. As a cautionary measure, the value of _noteNum will also be set to zero if _noteNum is not a number or if it has the value of "Not a Number", which is considered a number by JavaScript.*/
<<if ndef _noteNum or typeof _noteNum !== "number" or isNaN(_noteNum) is true>>
<<set _noteNum to 0>>
/*If _noteNum is both defined and a number, it will be incremented to ensure each note in a given passage has a unique number.*/
<<else>>
<<set _noteNum++>>
<</if>>
/*If the programmer gave at least one argument and that argument is not the number zero, _note will be set to that argument. Otherwise, it will be checked if _noteDefault is defined or if $noteDefault is defined, and if either is defined then _note will be set to one of them, with the temporary variable _noteDefault having precedence over the story variable $noteDefault. If neither are defined, _note will be set to the built-in default message, "No note provided".*/
<<if def _args[0] and _args[0] is not 0>>
<<set _note to _args[0]>>
<<elseif def _noteDefault>>
<<set _note to _noteDefault>>
<<elseif def $noteDefault>>
<<set _note to $noteDefault>>
<<else>>
<<set _note to "No note provided.">>
<</if>>
/*If the programmer gave a second argument and that argument is not the number zero nor an empty string, _noteName will be set to that argument. Otherwise, it will be checked if _noteNameDefault is defined or if $noteNameDefault is defined, and if either is defined then _noteName will be set to one of them, with the temporary variable _noteNameDefault having precedence over the story variable $noteNameDefault. If neither are defined, _noteName will be set to the built-in default name, "Note".*/
<<if def _args[1] and !(["", 0].includes(_args[1]))>>
<<set _noteName to _args[1]>>
<<elseif def _noteNameDefault>>
<<set _noteName to _noteNameDefault>>
<<elseif def $noteNameDefault>>
<<set _noteName to $noteNameDefault>>
<<else>>
<<set _noteName to "Note">>
<</if>>
/*If the programmer gave a third argument and that argument is not the number zero nor an empty string, _collapseNote will be set to that argument. Otherwise, it will be checked if _collapseNoteDefault is defined or if $collapseNoteDefault is defined, and if either is defined then _collapseNote will be set to one of them, with the temporary variable _collapseNoteDefault having precedence over the story variable $collapseNoteDefault. If neither are defined, _collapseNote will be set to the built-in default name, "Collapse Note".*/
<<if def _args[2] and !(["", 0].includes(_args[2]))>>
<<set _collapseNote to _args[2]>>
<<elseif def _collapseNoteDefault>>
<<set _collapseNote to _collapseNoteDefault>>
<<elseif def $collapseNoteDefault>>
<<set _collapseNote to $collapseNoteDefault>>
<<else>>
<<set _collapseNote to "Collapse Note">>
<</if>>
/*If the programmer gave a fourth argument, _collapseMode will be set to that argument. Otherwise, it will be checked if _collapseModeDefault is defined or if $collapseModeDefault is defined, and if either is defined then _collapseMode will be set to one of them, with the temporary variable _collapseModeDefault having precedence over the story variable $collapseModeDefault. If neither are defined, _collapseMode will be set to the built-in default value, 0. There are four possible values: 0, 1, 2, and 3. Any other value will act identically to 0.*/
<<if def _args[3]>>
<<set _collapseMode to _args[3]>>
<<elseif def _collapseModeDefault>>
<<set _collapseMode to _collapseModeDefault>>
<<elseif def $collapseModeDefault>>
<<set _collapseMode to $collapseModeDefault>>
<<else>>
<<set _collapseMode to 0>>
<</if>>
/*The five variables determined by the previous if-else statements are then captured, so that the variable names may be reused for later notes while keeping their values the same for this particular note.*/
<<capture _noteNum, _note, _noteName, _collapseNote, _collapseMode>>
/*The <<noteText>> widget, which contains the parts of the note visible to the end-user, is then called within a span. This span is given an ID consisting of the word "note" concatenated with the note number, such that each note has a unique ID to later be targeted by <<replace>> macros.*/
<span @id="'note' + _noteNum">
<<noteText>>
</span>
<</capture>>
<</widget>>
/*The <<noteText>> widget is what the program will call to display the details of a specific note.*/
<<widget "noteText">>
/*Collapse Modes*/
/*0: _collapseNote's value is displayed to the right of the text.*/
/*1: _collapseNote's value is displayed to the left of the text.*/
/*2: _collapseNote's value is not displayed, and _note instead serves as the "collapse note" text.*/
/*3: _collapseNote's value is not displayed, and the note cannot be collapsed.*/
/*End of Collapse Modes*/
/*The first thing displayed to the user is a link consisting of _noteName's value in superscript. When the link is clicked, the code between the <<link>> and <</link>> macros is ran.*/
<<link `"^^_noteName^^"`>>
/*The span with the ID corresponding to _noteNum will be replaced with that which is inside the <<replace>> macro.*/
<<replace `"#note" + _noteNum`>>
/*The placement of the "collapse note" text is determined first, so the second mode is excluded, as it changes the roles of the different texts.*/
<<if _collapseMode is not 2>>
/*If _collapseMode is set to 1, the "collapse note" text is displayed as a superscripted link before the text of _note.*/
<<if _collapseMode is 1>>
/*When clicked, the link will replace the span with the ID corresponding to _noteNum with the <<noteText>> widget, resetting it to its original, unclicked state.*/
<<link `"^^_collapseNote^^"`>>
<<replace `"#note" + _noteNum`>>
<<noteText>>
<</replace>>
<</link>>
<</if>>
/*The text of the note is displayed in superscript.*/
^^_note^^
/*If the _collapseMode is not set to 1 or 3, the "collapse note" text is displayed as a superscripted link after the text of _note. The if statement excludes 1 and 3 rather than including 0 and 2 to allow for the programmer to set _collapseMode to any value and have it act like 0.*/
<<if !([1,3].includes(_collapseMode))>>
/*When clicked, the link will replace the span with the ID corresponding to _noteNum with the <<noteText>> widget, resetting it to its original, unclicked state.*/
<<link `"^^_collapseNote^^"`>>
<<replace `"#note" + _noteNum`>>
<<noteText>>
<</replace>>
<</link>>
<</if>>
/*If the value of _collapseMode is 2, the text of _note will be displayed as a superscripted link, and _collapseNote will not be used.*/
<<else>>
/*When clicked, the link will replace the span with the ID corresponding to _noteNum with the <<noteText>> widget, resetting it to its original, unclicked state.*/
<<link `"^^_note^^"`>>
<<replace `"#note" + _noteNum`>>
<<noteText>>
<</replace>>
<</link>>
<</if>>
<</replace>>
<</link>>
<</widget>></nowiki></pre>
<h2>Expanded Code, without Comments</h2>\
><pre><nowiki><<widget "note">>
<<if ndef _noteNum or typeof _noteNum !== "number" or isNaN(_noteNum) is true>>
<<set _noteNum to 0>>
<<else>>
<<set _noteNum++>>
<</if>>
<<if def _args[0] and _args[0] is not 0>>
<<set _note to _args[0]>>
<<elseif def _noteDefault>>
<<set _note to _noteDefault>>
<<elseif def $noteDefault>>
<<set _note to $noteDefault>>
<<else>>
<<set _note to "No note provided.">>
<</if>>
<<if def _args[1] and !(["", 0].includes(_args[1]))>>
<<set _noteName to _args[1]>>
<<elseif def _noteNameDefault>>
<<set _noteName to _noteNameDefault>>
<<elseif def $noteNameDefault>>
<<set _noteName to $noteNameDefault>>
<<else>>
<<set _noteName to "Note">>
<</if>>
<<if def _args[2] and !(["", 0].includes(_args[2]))>>
<<set _collapseNote to _args[2]>>
<<elseif def _collapseNoteDefault>>
<<set _collapseNote to _collapseNoteDefault>>
<<elseif def $collapseNoteDefault>>
<<set _collapseNote to $collapseNoteDefault>>
<<else>>
<<set _collapseNote to "Collapse Note">>
<</if>>
<<if def _args[3]>>
<<set _collapseMode to _args[3]>>
<<elseif def _collapseModeDefault>>
<<set _collapseMode to _collapseModeDefault>>
<<elseif def $collapseModeDefault>>
<<set _collapseMode to $collapseModeDefault>>
<<else>>
<<set _collapseMode to 0>>
<</if>>
<<capture _noteNum, _note, _noteName, _collapseNote, _collapseMode>>
<span @id="'note' + _noteNum">
<<noteText>>
</span>
<</capture>>
<</widget>>
<<widget "noteText">>
<<link `"^^_noteName^^"`>>
<<replace `"#note" + _noteNum`>>
<<if _collapseMode is not 2>>
<<if _collapseMode is 1>>
<<link `"^^_collapseNote^^"`>>
<<replace `"#note" + _noteNum`>>
<<noteText>>
<</replace>>
<</link>>
<</if>>
^^_note^^
<<if !([1,3].includes(_collapseMode))>>
<<link `"^^_collapseNote^^"`>>
<<replace `"#note" + _noteNum`>>
<<noteText>>
<</replace>>
<</link>>
<</if>>
<<else>>
<<link `"^^_note^^"`>>
<<replace `"#note" + _noteNum`>>
<<noteText>>
<</replace>>
<</link>>
<</if>>
<</replace>>
<</link>>
<</widget>></nowiki></pre>
<h2>twineNotes Lite</h2>\
twineNotes Lite is an alternate version of twineNotes that strips things down to the bare essentials. This version only allows for setting the note's message, and has no support for changing the note's open or collapse text nor its mode, and also lacks the ability to set defaults beyond changing the actual widget code.
><pre style="white-space: pre-wrap; "><nowiki><<widget "note">><<if ndef _noteNum or typeof _noteNum !== "number" or isNaN(_noteNum) is true>><<set _noteNum to 0>><<else>><<set _noteNum++>><</if>><<if def _args[0]>><<set _note to _args[0]>><<else>><<set _note to "No note provided.">><</if>><<capture _noteNum, _note>><span @id="'note' + _noteNum"><<noteText>></span><</capture>><</widget>>
<<widget "noteText">><<link `"^^Note^^"`>><<replace `"#note" + _noteNum`>>^^_note^^ <<link `"^^Collapse Note^^"`>><<replace `"#note" + _noteNum`>><<noteText>><</replace>><</link>><</replace>><</link>><</widget>></nowiki></pre>
For usage alongside twineNotes, there is also a version with renamed widgets.
><pre style="white-space: pre-wrap; "><nowiki><<widget "noteLite">><<if ndef _noteNum or typeof _noteNum !== "number" or isNaN(_noteNum) is true>><<set _noteNum to 0>><<else>><<set _noteNum++>><</if>><<if def _args[0]>><<set _note to _args[0]>><<else>><<set _note to "No note provided.">><</if>><<capture _noteNum, _note>><span @id="'note' + _noteNum"><<noteLiteText>></span><</capture>><</widget>>
<<widget "noteLiteText">><<link `"^^Note^^"`>><<replace `"#note" + _noteNum`>>^^_note^^ <<link `"^^Collapse Note^^"`>><<replace `"#note" + _noteNum`>><<noteLiteText>><</replace>><</link>><</replace>><</link>><</widget>></nowiki></pre><<nobr>>
/*Notes Lite Widgets*/
<<widget "noteLite">><<if ndef _noteNum or typeof _noteNum !== "number" or isNaN(_noteNum) is true>><<set _noteNum to 0>><<else>><<set _noteNum++>><</if>><<if def _args[0]>><<set _note to _args[0]>><<else>><<set _note to "No note provided.">><</if>><<capture _noteNum, _note>><span @id="'note' + _noteNum"><<noteLiteText>></span><</capture>><</widget>>
<<widget "noteLiteText">><<link `"^^Note^^"`>><<replace `"#note" + _noteNum`>>^^_note^^ <<link `"^^Collapse Note^^"`>><<replace `"#note" + _noteNum`>><<noteLiteText>><</replace>><</link>><</replace>><</link>><</widget>>
/*Notes Widgets*/
<<widget "note">><<if ndef _noteNum or typeof _noteNum !== "number" or isNaN(_noteNum) is true>><<set _noteNum to 0>><<else>><<set _noteNum++>><</if>><<if def _args[0] and _args[0] is not 0>><<set _note to _args[0]>><<elseif def _noteDefault>><<set _note to _noteDefault>><<elseif def $noteDefault>><<set _note to $noteDefault>><<else>><<set _note to "No note provided.">><</if>><<if def _args[1] and !(["", 0].includes(_args[1]))>><<set _noteName to _args[1]>><<elseif def _noteNameDefault>><<set _noteName to _noteNameDefault>><<elseif def $noteNameDefault>><<set _noteName to $noteNameDefault>><<else>><<set _noteName to "Note">><</if>><<if def _args[2] and !(["", 0].includes(_args[2]))>><<set _collapseNote to _args[2]>><<elseif def _collapseNoteDefault>><<set _collapseNote to _collapseNoteDefault>><<elseif def $collapseNoteDefault>><<set _collapseNote to $collapseNoteDefault>><<else>><<set _collapseNote to "Collapse Note">><</if>><<if def _args[3]>><<set _collapseMode to _args[3]>><<elseif def _collapseModeDefault>><<set _collapseMode to _collapseModeDefault>><<elseif def $collapseModeDefault>><<set _collapseMode to $collapseModeDefault>><<else>><<set _collapseMode to 0>><</if>><<capture _noteNum, _note, _noteName, _collapseNote, _collapseMode>><span @id="'note' + _noteNum"><<noteText>></span><</capture>><</widget>>
<<widget "noteText">><<link `"^^_noteName^^"`>><<replace `"#note" + _noteNum`>><<if _collapseMode is not 2>><<if _collapseMode is 1>><<link `"^^_collapseNote^^"`>><<replace `"#note" + _noteNum`>><<noteText>><</replace>><</link>> <</if>>^^_note^^ <<if !([1,3].includes(_collapseMode))>><<link `"^^_collapseNote^^"`>><<replace `"#note" + _noteNum`>><<noteText>><</replace>><</link>><</if>><<else>><<link `"^^_note^^"`>><<replace `"#note" + _noteNum`>><<noteText>><</replace>><</link>><</if>><</replace>><</link>><</widget>>
<</nobr>>