klembot / twinejs

Twine, a tool for telling interactive, nonlinear stories
https://twinery.org
GNU General Public License v3.0
2.05k stars 309 forks source link

Multiple scripts and stylesheets #1574

Open cjneidhart opened 3 days ago

cjneidhart commented 3 days ago

Is your feature request related to a problem? Please describe.

Users that make extensive use of JS and CSS can easily find themselves working with a script or stylesheet that is extremely long, with no easy way to break it apart. When writing prose in a passage, every format has an easy solution to this problem (e.g. (display: ) in Harlowe). But there is no simple way to break apart scripts or stylesheets, leading users to awkward solutions such as tagging passages with script or stylesheet and manually loading them at startup.

Describe the solution you'd like.

The behavior of the "JavaScript" and "Stylesheet" buttons in the "Story" menubar would be changed. When clicked (or tapped or otherwise fired), a list of each script/stylesheet would be shown, alongside a "handle" the user can use to reorder the scripts/stylesheets. At the bottom of the list would be a button to add a new script/stylesheet. Clicking one of the script/stylesheet's names would open the editor for that script/stylesheet. Editing multiple scripts at once would cause them to stack and editing multiple stylesheets at once causes a stack, just like editing multiple passages at once causes them to stack.

The script/stylesheet editors would have a new button on their toolbar, "Rename". This would allow the user to rename that script/stylesheet.

When the story is built, all scripts will be concatenated into one <script> element, and all stylesheets will be concatenated into one <style> element. Potentially, comments could be added to the output, indicating where each pseudo-passage begins.

It is worth noting that all 4 built-in formats support multiple <script> and <style> elements within <tw-storydata>. However, changing the specification of Twine 2's output is unnecessary and offers little benefit.

This solution would necessitate a change in the storage format of Twine; either a Script type and Stylesheet type would need to be created, or a single PseudoPassage type could be used to cover both. These types might look like:

type Stylesheet {
  // ID of the parent story
  story: string;
  // The name of this stylesheet, to distinguish it from others in the same story
  name: string;
  // Body text of the stylesheet
  text: string;
}

Describe alternatives you've considered.

The only alternative to this problem I can find is to continue using bespoke tags to emulate having multiple scripts or stylesheets. However, this is cumbersome and overly reliant on the story format to enable it. It also plays poorly with syntax highlighting, since codemirror modes have no way of realizing these passages are not regular markup.

Additional context on this suggestion.

This issue is similar to #509. However, this issue is more specific and easier to implement. It can also be seen as a "stepping stone" on the way to implementing a repository-based module system, if that's desired in the future.

Presubmission checklist

cjneidhart commented 3 days ago

Open questions