Move HTML generation back to JavaScript.
- Functionality maintained - File operations removed from server - Browsers should again be able to cache the tutorial
This commit is contained in:
parent
87ea87a2e9
commit
b47e8cbbf2
|
@ -10,7 +10,6 @@ from flask import Flask, request, redirect, url_for, render_template, Response,
|
||||||
from flask_caching import Cache
|
from flask_caching import Cache
|
||||||
from flaskext.autoversion import Autoversion
|
from flaskext.autoversion import Autoversion
|
||||||
from flask_compress import Compress
|
from flask_compress import Compress
|
||||||
import markdown
|
|
||||||
|
|
||||||
from .models import *
|
from .models import *
|
||||||
|
|
||||||
|
@ -76,14 +75,8 @@ def register_session():
|
||||||
|
|
||||||
@app.route('/tutorial')
|
@app.route('/tutorial')
|
||||||
@app.route('/tutorial/<string:lang>')
|
@app.route('/tutorial/<string:lang>')
|
||||||
@cache.memoize(timeout=300) # update every 300 seconds
|
|
||||||
def tutorial(lang='en'):
|
def tutorial(lang='en'):
|
||||||
try:
|
return render_template(f"tutorial.html", lang=lang)
|
||||||
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()))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/seed/<suuid:seed>')
|
@app.route('/seed/<suuid:seed>')
|
||||||
|
|
|
@ -5,4 +5,3 @@ flask-caching>=1.9.0
|
||||||
Flask-Autoversion>=0.2.0
|
Flask-Autoversion>=0.2.0
|
||||||
Flask-Compress>=1.5.0
|
Flask-Compress>=1.5.0
|
||||||
Flask-Limiter>=1.3.1
|
Flask-Limiter>=1.3.1
|
||||||
markdown>=3.2.2
|
|
|
@ -1,15 +1,48 @@
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
const headers = Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6'));
|
const tutorialWrapper = document.getElementById('tutorial-wrapper');
|
||||||
const scrollTargetIndex = window.location.href.search(/#[A-z0-9-_]*$/);
|
new Promise((resolve, reject) => {
|
||||||
for (let i=1; i < headers.length; i++){
|
const ajax = new XMLHttpRequest();
|
||||||
const headerId = headers[i].innerText.replace(/[ ]/g,'-').toLowerCase()
|
ajax.onreadystatechange = () => {
|
||||||
headers[i].setAttribute('id', headerId);
|
if (ajax.readyState !== 4) { return; }
|
||||||
headers[i].addEventListener('click', () =>
|
if (ajax.status === 404) {
|
||||||
window.location.href = window.location.href.substring(0, scrollTargetIndex) + `#${headerId}`);
|
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) {
|
// Reset the id of all header divs to something nicer
|
||||||
const scrollTarget = window.location.href.substring(scrollTargetIndex + 1);
|
const headers = Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6'));
|
||||||
document.getElementById(scrollTarget).scrollIntoView({ behavior: "smooth" });
|
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 =
|
||||||
|
`<h2>${error}</h2>
|
||||||
|
<h3>Click <a href="${window.location.origin}/tutorial">here</a> to return to safety.</h3>`;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -55,13 +55,11 @@ the players folder and is called `easy.yaml`
|
||||||
|
|
||||||
### Your YAML file is weighted
|
### Your YAML file is weighted
|
||||||
Throughout your YAML file, you will see many options which look similar to this:
|
Throughout your YAML file, you will see many options which look similar to this:
|
||||||
<pre>
|
```yaml
|
||||||
```
|
|
||||||
map_shuffle:
|
map_shuffle:
|
||||||
on: 5
|
on: 5
|
||||||
off: 15
|
off: 15
|
||||||
```
|
```
|
||||||
</pre>
|
|
||||||
In the above example, imagine the generator creates a bucket labelled "map_shuffle", and places a folded
|
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:
|
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
|
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.
|
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:
|
If you would like to add a sprite to the list, simply include its name and give it a weight like so:
|
||||||
<pre>
|
```yaml
|
||||||
```
|
|
||||||
rom:
|
rom:
|
||||||
sprite: # Enter the name of your preferred sprite and weight it appropriately
|
sprite: # Enter the name of your preferred sprite and weight it appropriately
|
||||||
random: 0
|
random: 0
|
||||||
|
@ -95,7 +92,6 @@ rom:
|
||||||
rocko: 5
|
rocko: 5
|
||||||
luigi: 3
|
luigi: 3
|
||||||
```
|
```
|
||||||
</pre>
|
|
||||||
|
|
||||||
### Verifying your YAML file
|
### Verifying your YAML file
|
||||||
If you would like to validate your YAML file to make sure it works, you may do so on the
|
If you would like to validate your YAML file to make sure it works, you may do so on the
|
|
@ -3,11 +3,14 @@
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<title>Setup Tutorial</title>
|
<title>Setup Tutorial</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/tutorial.css") }}" />
|
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/tutorial.css") }}" />
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.9.1/showdown.min.js"
|
||||||
|
integrity="sha512-L03kznCrNOfVxOUovR6ESfCz9Gfny7gihUX/huVbQB9zjODtYpxaVtIaAkpetoiyV2eqWbvxMH9fiSv5enX7bw=="
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
<script type="application/ecmascript" src="{{ static_autoversion("assets/tutorial.js") }}"></script>
|
<script type="application/ecmascript" src="{{ static_autoversion("assets/tutorial.js") }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div id="tutorial-wrapper" class="main-content">
|
<div id="tutorial-wrapper" class="main-content" data-language="{{ lang }}">
|
||||||
{{ tutorial|safe }}
|
<!-- Content generated by JavaScript -->
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Reference in New Issue