text: window.storyFormat({"name":"Stellaris","version":"1.0.0","source":"<!DOCTYPE html>\r\n<html lang=\"en\">\r\n\r\n<head>\r\n  <meta charset=\"UTF-8\">\r\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n  <title>{{STORY_NAME}}</title>\r\n</head>\r\n\r\n<body>\r\n  {{STORY_DATA}}\r\n  <style>\r\n    * {\r\n      margin: 0;\r\n      padding: 0;\r\n    }\r\n\r\n    body {\r\n      width: 100vw;\r\n      height: 100vh;\r\n      display: flex;\r\n      justify-content: center;\r\n      align-items: center;\r\n      background-image: radial-gradient(circle, #2b372d, #283732, #273737, #29373a, #2d363b, #2e373c, #30373c, #31383d, #303a3e, #303c3f, #303d3f, #313f3e);\r\n    }\r\n\r\n    tw-passage {\r\n      background-color: #162c1fee;\r\n      color: white;\r\n      padding: 10px 25px;\r\n      width: 500px;\r\n      box-sizing: border-box;\r\n    }\r\n\r\n    tw-passage h1 {\r\n      text-shadow: #3b755dee 1px 0 20px;\r\n      border-bottom: 2px solid #324941ee;\r\n      padding-bottom: 5px;\r\n      margin-bottom: 10px;\r\n    }\r\n\r\n    tw-passage a {\r\n      display: block;\r\n      text-decoration: none;\r\n    }\r\n\r\n    tw-passage button,\r\n    tw-passage a {\r\n      display: block;\r\n      width: 100%;\r\n      color: white;\r\n      text-align: center;\r\n    }\r\n\r\n    tw-passage button {\r\n      margin-bottom: 5px;\r\n      padding: 2.5px 0;\r\n      border: 1px solid #324941ee;\r\n      background-color: #202c22ee;\r\n      position: relative;\r\n    }\r\n\r\n    tw-passage button:hover::before,\r\n    tw-passage button:hover::after {\r\n      content: '';\r\n      position: absolute;\r\n      width: 2.5%;\r\n      height: 100%;\r\n      top: 0;\r\n      border-top: 2px solid #dd960896;\r\n      border-bottom: 2px solid #dd960896;\r\n      box-sizing: border-box;\r\n    }\r\n\r\n    tw-passage button:hover::before {\r\n      left: 0;\r\n      border-left: 2px solid #dd960896;\r\n    }\r\n\r\n    tw-passage button:hover::after {\r\n      right: 0;\r\n      border-right: 2px solid #dd960896;\r\n    }\r\n\r\n    tw-passage button:hover {\r\n      background: linear-gradient(0deg, #dd96081a 45%, #dd96085d 45%, #dd96085d 55%, #dd96081a 55%, #dd96081a 100%);\r\n      background-size: 400% 400%;\r\n\r\n      -webkit-animation: scrolling 2s linear infinite;\r\n      -moz-animation: scrolling 2s linear infinite;\r\n      animation: scrolling 2s linear infinite;\r\n    }\r\n\r\n    tw-passage img {\r\n      width: 450px;\r\n      height: 150px;\r\n      display: block;\r\n      border: 2px solid #324941ee;\r\n      margin-bottom: 15px;\r\n      box-sizing: border-box;\r\n    }\r\n\r\n    tw-passage article {\r\n      background-color: #161d1798;\r\n      padding: 12.5px;\r\n      border: 1px solid #3d574eee;\r\n      margin-bottom: 15px;\r\n      color: #a8dbc4;\r\n    }\r\n\r\n    tw-passage article p {\r\n      margin: 10px 0;\r\n    }\r\n\r\n    @-webkit-keyframes scrolling {\r\n      0% {\r\n        background-position: 50% 100%\r\n      }\r\n\r\n      100% {\r\n        background-position: 50% 0%\r\n      }\r\n    }\r\n\r\n    @-moz-keyframes scrolling {\r\n      0% {\r\n        background-position: 50% 100%\r\n      }\r\n\r\n      100% {\r\n        background-position: 50% 0%\r\n      }\r\n    }\r\n\r\n    @keyframes scrolling {\r\n      0% {\r\n        background-position: 50% 100%\r\n      }\r\n\r\n      100% {\r\n        background-position: 50% 0%\r\n      }\r\n    }\r\n  </style>\r\n  <script>\r\n    (() => {\r\n      function createButtons(content) {\r\n        const buttonRegExp = /\\[\\[.*?\\]\\]/g;\r\n        let i = 0;\r\n\r\n        const parsedContent = content.replace(buttonRegExp, (match) => {\r\n          let display = match.replace(/[\\[\\]]/g, \"\");\r\n          let target = null;\r\n          let articleEndTag = '';\r\n\r\n          if (display.includes(\"-&gt;\")) {\r\n            [display, target] = display.split(\"-&gt;\").map(el => el.trim());\r\n          }\r\n\r\n          if (i === 0) {\r\n            articleEndTag = \"</article>\";\r\n          }\r\n\r\n          i++;\r\n\r\n          if (target) {\r\n            return `${articleEndTag}<button><a href=\"javascript:void(0)\" data-passage=\"${target}\">${display}</a></button>`;\r\n          } else {\r\n            return `${articleEndTag}<button>${display}</button>`;\r\n          }\r\n        });\r\n\r\n        return parsedContent;\r\n      }\r\n\r\n      function createTitle(content) {\r\n        const titleRegExp = /!!.*?!!/;\r\n\r\n        const parsedContent = content.replace(titleRegExp, (match) => {\r\n          const display = match.replace(/!!/g, \"\");\r\n\r\n          return `<h1>${display}</h1>`;\r\n        });\r\n\r\n        return parsedContent;\r\n      }\r\n\r\n      function createPicture(content) {\r\n        const imageRegExp = /\\(picture:.*?\\)/;\r\n        let found = false;\r\n\r\n        const parsedContent = content.replace(imageRegExp, (match) => {\r\n          const imgURL = match.replace(\"picture:\", \"\").slice(1, -1);\r\n          found = true;\r\n\r\n          return `<img src=\"${imgURL}\" /><article>`;\r\n        });\r\n\r\n        return parsedContent;\r\n      }\r\n\r\n      function createDescription(content) {\r\n        const descriptionRegExp = /<article>(.*?|\\n)*?<\\/article>/;\r\n\r\n        const parsedContent = content.replace(descriptionRegExp, (match) => {\r\n          const paragraphs = match\r\n            .split(\"\\n\")\r\n            .filter(item => item !== \"<article>\" && item !== \"<article/>\" && item.length)\r\n            .map(item => `<p>${item.trim()}</p>`)\r\n            .join(\"\");\r\n\r\n          return `<article>${paragraphs}</article>`;\r\n        });\r\n\r\n        return parsedContent;\r\n      }\r\n\r\n      function parse(content) {\r\n        const functions = [createTitle, createPicture, createButtons, createDescription];\r\n        const parsed = functions.reduce((parsedContent, currentFunction) => currentFunction(parsedContent), content);\r\n\r\n        return parsed;\r\n      }\r\n\r\n      function findPassageByPid(pid) {\r\n        return document.querySelector(`[pid = \"${pid}\"]`);\r\n      }\r\n\r\n      function findPassageByName(name) {\r\n        return document.querySelector(`[name = \"${name}\"]`);\r\n      }\r\n\r\n      function handleButtonClick({ target }) {\r\n        let passageName = target.attributes[\"data-passage\"].value;\r\n        let passageData = findPassageByName(passageName);\r\n        showPassage(passageData);\r\n      }\r\n\r\n      function showPassage(passageData) {\r\n        let passage = document.querySelector('tw-passage');\r\n\r\n        if (passage === null) {\r\n          passage = document.createElement('tw-passage');\r\n        }\r\n\r\n        let links = passage.querySelectorAll('a[data-passage]');\r\n\r\n        links.forEach(link => {\r\n          link.removeEventListener('click', handleButtonClick);\r\n        });\r\n\r\n        passage.innerHTML = parse(passageData.innerHTML);\r\n\r\n        links = passage.querySelectorAll('a[data-passage]');\r\n\r\n        links.forEach(link => {\r\n          link.addEventListener('click', handleButtonClick);\r\n        });\r\n\r\n        document.body.appendChild(passage);\r\n      }\r\n\r\n      let storyData = document.querySelector('tw-storydata');\r\n      let startNode = storyData.attributes['startnode'].value;\r\n      let passageData = findPassageByPid(startNode);\r\n\r\n      showPassage(passageData)\r\n    })();\r\n  </script>\r\n</body>\r\n\r\n</html>","description":"Stellaris story format"})