From b47e8cbbf21136eda7f2e49043cd74d58f736027 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Aug 2020 20:09:59 -0400 Subject: [PATCH] Move HTML generation back to JavaScript. - Functionality maintained - File operations removed from server - Browsers should again be able to cache the tutorial --- WebHostLib/__init__.py | 9 +-- WebHostLib/requirements.txt | 1 - WebHostLib/static/assets/tutorial.js | 57 +++++++++++++++---- .../assets}/tutorial/tutorial_en.md | 8 +-- WebHostLib/templates/tutorial.html | 7 ++- 5 files changed, 53 insertions(+), 29 deletions(-) rename WebHostLib/{ => static/assets}/tutorial/tutorial_en.md (99%) diff --git a/WebHostLib/__init__.py b/WebHostLib/__init__.py index cc804850..ea7c0158 100644 --- a/WebHostLib/__init__.py +++ b/WebHostLib/__init__.py @@ -10,7 +10,6 @@ from flask import Flask, request, redirect, url_for, render_template, Response, from flask_caching import Cache from flaskext.autoversion import Autoversion from flask_compress import Compress -import markdown from .models import * @@ -76,14 +75,8 @@ def register_session(): @app.route('/tutorial') @app.route('/tutorial/') -@cache.memoize(timeout=300) # update every 300 seconds def tutorial(lang='en'): - try: - md_file = open(os.path.join('WebHostLib', 'tutorial', f"tutorial_{lang}.md"), encoding="utf-8-sig") - except FileNotFoundError: - return render_template("tutorial.html", tutorial='The tutorial is not available in that language yet, sorry.') - else: - return render_template("tutorial.html", tutorial=markdown.markdown(md_file.read())) + return render_template(f"tutorial.html", lang=lang) @app.route('/seed/') diff --git a/WebHostLib/requirements.txt b/WebHostLib/requirements.txt index 27e0aac8..4c02005b 100644 --- a/WebHostLib/requirements.txt +++ b/WebHostLib/requirements.txt @@ -5,4 +5,3 @@ flask-caching>=1.9.0 Flask-Autoversion>=0.2.0 Flask-Compress>=1.5.0 Flask-Limiter>=1.3.1 -markdown>=3.2.2 \ No newline at end of file diff --git a/WebHostLib/static/assets/tutorial.js b/WebHostLib/static/assets/tutorial.js index 8d9b6861..52626f2a 100644 --- a/WebHostLib/static/assets/tutorial.js +++ b/WebHostLib/static/assets/tutorial.js @@ -1,15 +1,48 @@ window.addEventListener('load', () => { - const headers = Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6')); - const scrollTargetIndex = window.location.href.search(/#[A-z0-9-_]*$/); - for (let i=1; i < headers.length; i++){ - const headerId = headers[i].innerText.replace(/[ ]/g,'-').toLowerCase() - headers[i].setAttribute('id', headerId); - headers[i].addEventListener('click', () => - window.location.href = window.location.href.substring(0, scrollTargetIndex) + `#${headerId}`); - } + const tutorialWrapper = document.getElementById('tutorial-wrapper'); + new Promise((resolve, reject) => { + const ajax = new XMLHttpRequest(); + ajax.onreadystatechange = () => { + if (ajax.readyState !== 4) { return; } + if (ajax.status === 404) { + reject("Sorry, the tutorial is not available in that language yet."); + return; + } + if (ajax.status !== 200) { + reject("Something went wrong while loading the tutorial."); + return; + } + resolve(ajax.responseText); + }; + ajax.open('GET', `${window.location.origin}/static/assets/tutorial/tutorial_` + + `${tutorialWrapper.getAttribute('data-language')}.md`, true); + ajax.send(); + }).then((results) => { + // Populate page with HTML generated from markdown + tutorialWrapper.innerHTML = (new showdown.Converter()).makeHtml(results); - if (scrollTargetIndex > -1) { - const scrollTarget = window.location.href.substring(scrollTargetIndex + 1); - document.getElementById(scrollTarget).scrollIntoView({ behavior: "smooth" }); - } + // Reset the id of all header divs to something nicer + const headers = Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6')); + const scrollTargetIndex = window.location.href.search(/#[A-z0-9-_]*$/); + for (let i=0; i < headers.length; i++){ + const headerId = headers[i].innerText.replace(/[ ]/g,'-').toLowerCase() + headers[i].setAttribute('id', headerId); + headers[i].addEventListener('click', () => + window.location.href = window.location.href.substring(0, scrollTargetIndex) + `#${headerId}`); + } + + // Manually scroll the user to the appropriate header if anchor navigation is used + if (scrollTargetIndex > -1) { + try{ + const scrollTarget = window.location.href.substring(scrollTargetIndex + 1); + document.getElementById(scrollTarget).scrollIntoView({ behavior: "smooth" }); + } catch(error) { + console.error(error); + } + } + }).catch((error) => { + tutorialWrapper.innerHTML = + `

${error}

+

Click here to return to safety.

`; + }); }); diff --git a/WebHostLib/tutorial/tutorial_en.md b/WebHostLib/static/assets/tutorial/tutorial_en.md similarity index 99% rename from WebHostLib/tutorial/tutorial_en.md rename to WebHostLib/static/assets/tutorial/tutorial_en.md index 7c957ad9..ccc19295 100644 --- a/WebHostLib/tutorial/tutorial_en.md +++ b/WebHostLib/static/assets/tutorial/tutorial_en.md @@ -55,13 +55,11 @@ the players folder and is called `easy.yaml` ### Your YAML file is weighted Throughout your YAML file, you will see many options which look similar to this: -
-```
+```yaml
 map_shuffle:
   on: 5
   off: 15
 ```
-
In the above example, imagine the generator creates a bucket labelled "map_shuffle", and places a folded piece of paper into the bucket for each sub-option. Here, there are twenty pieces of paper in the bucket: five for "on" and fifteen for "off". When the generator is deciding whether or not to turn on map shuffle @@ -83,8 +81,7 @@ which do not affect gameplay. These options are also weighted, in case you want of your hearts or by the silliness of your overworld palette. If you would like to add a sprite to the list, simply include its name and give it a weight like so: -
-```
+```yaml
 rom:
   sprite: # Enter the name of your preferred sprite and weight it appropriately
     random: 0
@@ -95,7 +92,6 @@ rom:
     rocko: 5
     luigi: 3
 ```
-
### Verifying your YAML file If you would like to validate your YAML file to make sure it works, you may do so on the diff --git a/WebHostLib/templates/tutorial.html b/WebHostLib/templates/tutorial.html index a421f550..9e751464 100644 --- a/WebHostLib/templates/tutorial.html +++ b/WebHostLib/templates/tutorial.html @@ -3,11 +3,14 @@ {% block head %} Setup Tutorial + {% endblock %} {% block body %} -
- {{ tutorial|safe }} +
+
{% endblock %}