Text editor now has a new method for organizing things, and also it works with else ifs!
This commit is contained in:
parent
40448960bf
commit
3a139f5dc2
@ -1,305 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>How should this website be laid out?</title>
|
|
||||||
<link href="/static/bootstrap/css/bootstrap.css" rel="stylesheet" type="text/css">
|
|
||||||
<link href="/static/bootstrap/css/bootstrap-responsive.css" rel="stylesheet" type="text/css">
|
|
||||||
<link href="/static/shoofle.css" rel="stylesheet" type="text/css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<style type="text/css">
|
|
||||||
#server-choices colgroup { width: 20%; }
|
|
||||||
#server-choices tr { height: 3em; }
|
|
||||||
#server-choices tr>td { text-align: center; }
|
|
||||||
#server-choices tr>td:first-child {
|
|
||||||
text-align: left;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<article class="project">
|
|
||||||
<h1>Shit, I better make this server work.</h1>
|
|
||||||
<h3>On the layout of folders and files!</h3>
|
|
||||||
<p>Basically I'm not sure how I should lay out this website. The current organization looks something like this:</p>
|
|
||||||
<ul class="file-tree">
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">server/</span> (server root)
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">main_page.html</span></li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">pages/</span> (articles with nice links)
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">auriga.html</span> (accessed as <span class="url">http://example.com/auriga/</span>)</li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">language_for_games.html</span> (<span class="url">http://example.com/language-for-games/</span>)</li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">tamari.html</span> (<span class="url">http://example.com/tamari/</span>)
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">static/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-eye-open"></i> <span class="filename">stylesheet.css</span> (global stying)</li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">favicon.ico</span></li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">banner.png</span></li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">tamari/</span> (files for an article)
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">figure_1.png</span></li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">figure_2.png</span></li>
|
|
||||||
<li><i class="icon-signal"></i> <span class="filename">experiment_data.csv</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>This has a number of problems. First and foremost, barely any thought has gone into naming of folders and files - which is because not much thought has gone into their placement and hierarchy.</p>
|
|
||||||
<p>The server is written using <a href="http://flask.pocoo.org">Flask</a>, and this is the rundown on how it works when a user goes to <span class="url">http://example.com/some-path/</span>:</p>
|
|
||||||
<ol>
|
|
||||||
<li>If the path requested is the root of the website, render <span class="filename">main_page.html</span>.</li>
|
|
||||||
<li>If the path requested begins with <span class="url">static/</span>, render a file from the static content directory.</li>
|
|
||||||
<li>Else, convert the path (<span class="url">some-path</span>) into the filename (<span class="filename">pages/some_path.html</span>) assuming it's an article. If it exists, render it.</li>
|
|
||||||
<li>If there's no article by that name, display the miscellaneous articles page. Or 404. The current behavior isn't very high on my priorities.</li>
|
|
||||||
</ol>
|
|
||||||
<p>There are a bunch of problems with this system - it's kind of brittle, file paths have the meaningless-to-the-user <span class="url">static/</span> at the beginning, and it means that when I include a resource in <span class="url">http://example.com/tamari/</span> (the file <span class="filename">pages/tamari.html</span>) I have to use a path like <span class="url">../static/tamari/figure_1.png</span> - when I should be able to reference files related to the Tamari article by a closely-related URL: <span class="url">./figure_1.png</span>.</p>
|
|
||||||
<p>All this points to the idea of having my articles be in folders, so it would look something like this:</p>
|
|
||||||
<ul class="file-tree">
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">server/</span> (server root)
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">main_page.html</span></li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">articles/</span> (articles with nice links)
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">auriga/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">auriga.html</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">language-for-games/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">language_for_games.html</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">tamari/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">tamari.html</span></li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">figure_1.png</span></li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">figure_2.png</span></li>
|
|
||||||
<li><i class="icon-signal"></i> <span class="filename">experiment_data.csv</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">static/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-eye-open"></i> <span class="filename">stylesheet.css</span> (global stying)</li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">favicon.ico</span></li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">banner.png</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>And hell, at this point having the filenames match the folders (<span class="filename">auriga/auriga.html</span>) is just a pain, so we could name the main page in each folder <span class="filename">index.html</span>, and suddenly this looks very standard. So why don't I do this?</p>
|
|
||||||
<p>Well... I don't know. But something always bothered me about the <span class="filename">index.html</span> standard. Maybe it's just that my article about Tamari lattices <em>isn't</em> an index, so I don't think it should be called one. That's certainly part of it. Also, some of my articles and pages are going to be very short - in theory I'd like them to be able to be tiny snippets, which could be included on other pages. It'd be annoying to have a subfolder for every single article I write! But... maybe not <em>too</em> annoying. I'll have to think about that.</p>
|
|
||||||
<hr>
|
|
||||||
<h3>But what are we <em>doing</em>?</h3>
|
|
||||||
<p>What would my ideal web framework be? Well, something like Flask, really. I like flask because this is easy:</p>
|
|
||||||
<pre>
|
|
||||||
<code class="language-python">@app.route("<span class="url">/some-convoluted/url/<options>/with-stuff/</span>")
|
|
||||||
def render_shoofle_page(options=None):
|
|
||||||
if options == "bananas":
|
|
||||||
return render_page("<span class="filename">bananas.html</span>")
|
|
||||||
else:
|
|
||||||
return render_page("<span class="filename">some_other_template.html</span>", options=options)</code></pre>
|
|
||||||
<p>And, lo and behold, I can go to <span class="url">example.com/some-convoluted/url/bananas/with-stuff/</span> and see the right generated page! I like having that capacity at my fingertips. In particular, it makes it easy to respond to various other kinds of requests. That's what I really like about Flask - I feel like I can do <em>everything</em> a webserver can do, but it all takes the same very small amount of work. This compares to, say, PHP, where it's easy to make pages... But more complicated behavior, especially anything involving dynamic URL paths, involves jumping through hoops.<span class="sidenote span4">It might seem like an overblown complaint, but the integrity of my mental models is important to me - and in PHP, I don't understand what gets sent to the requestor. If I make a Flask route returning JSON, I know it's exactly what a script wants. With PHP, I would <em>hope</em> that it wouldn't have weird headers or content type or additional markup.</span> Plus, you have to work with PHP, which I would wish on no one.</p>
|
|
||||||
<p>I don't like Flask because I need to specify all the behaviors, and I'm worried that I'll get it wrong (thus, this article).</p>
|
|
||||||
<p>My ideal world solution would be something that lets me pass requests for subpaths to other python modules:<p>
|
|
||||||
<ul class="file-tree">
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">server/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-file"></i> <span class="filename">server.py</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">main_page.html</span></li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">articles/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-file"></i> <span class="filename">articles.py</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">auriga.html</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">language-for-games.html</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">tamari.html</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">games/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-file"></i> <span class="filename">games.py</span></li>
|
|
||||||
<li><i class="icon-signal"></i> <span class="filename">scores.csv</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">play_the_game.html</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">game.js</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>Aaaand how it works would be simple:</p>
|
|
||||||
<ol>
|
|
||||||
<li>A request comes in to <span class="url">http://example.com/tamari/</span>, and it is handled by <span class="filename">server.py</span>.</li>
|
|
||||||
<li><span class="filename">server.py</span> says "Okay, I don't have any specific handlers that do anything with this URL, but I think <span class="filename">articles/articles.py</span> does!" and sends the request to <span class="filename">articles.py</span>.</li>
|
|
||||||
<li><span class="filename">articles.py</span> receives a request for <span class="url">/tamari/</span> and has a rule for handling that, and so it renders the appropriate HTML file.</li>
|
|
||||||
</ol>
|
|
||||||
<p>The basic idea is that requests can be routed to other python modules. If those modules can be reloaded easily (or automatically!), this would mean I could write complicated URL handling in subdirectories of my website - without having to touch any of the code that handles anything else. It means I can modularize - and that's <em>awesome</em>.</p>
|
|
||||||
<ol>
|
|
||||||
<li>An HTTP GET request comes in to <span class="url">http://example.com/games/points</span>, and <span class="filename">server.py</span> takes it.</li>
|
|
||||||
<li><span class="filename">server.py</span> doesn't know what to do with it, but it knows that requests for URLs starting with <span class="url">/games</span> should be handled by <span class="filename">games/games.py</span>.</li>
|
|
||||||
<li><span class="filename">games.py</span> receives an HTTP GET request for <span class="url">/games/points</span>, and so it can respond to this with a JSON object that tells the requestor how many points they got.</li>
|
|
||||||
</ol>
|
|
||||||
<p>This is the main point of the tiered handlers system - that I can write handlers for all kinds of requests, without having to interact with other parts of my website.</p>
|
|
||||||
<p>Basically, I want to combine the simple directory structure of PHP websites with the principles of Flask I really like - separating content from server logic, keeping things simple, and having control.</p>
|
|
||||||
<p>Here's how I imagine this would work:</p>
|
|
||||||
<pre>
|
|
||||||
<code>from flask import Flask, render_template, redirect
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
def main_page(): return render_template("<span class="filename">main.html</span>")
|
|
||||||
app.add_url_rule("<span class="url">/</span>", main_page)
|
|
||||||
|
|
||||||
import games
|
|
||||||
app.add_module_url_rule("<span class="url">/games/<path:rest></span>", games)</code></pre>
|
|
||||||
<p>As usual, don't think too hard about the syntax I just proposed. The point is to distribute URL routing logic throughout multiple files, so that my entire website isn't controlled by one brutalistic overlord <span class="filename">server.py</span> file that decrees the entire path of every request. I want things split up, dammit!</p>
|
|
||||||
<hr>
|
|
||||||
<p>Now I'm reading up on the Flask docs, and it turns out that it already has the capacity for this. Unfortunately, it's complicated and I'm <em>whiiiny</em>.</p>
|
|
||||||
<p>It seems that Flask provides the developer with three options:</p>
|
|
||||||
<ul>
|
|
||||||
<li>Package Organization: Essentially, break up your server code, like configuration and URL route assignment, into separate files. This doesn't actually solve any of my issues - most of what this does (as far as I can tell) is separate the server initialization logic from the routing and response logic. Plus, it makes it easier to use your application in something else. More on this soon.</li>
|
|
||||||
<li>Blueprints: Very close to what I want. I could define a Blueprint object in <span class="filename">articles.py</span>. This Blueprint object would register all the routes and endpoints that I want to register - and then, when the server starts, it gets all of those from the blueprint. This means we can <em>actually</em> factor views out. I'm really not sure, though, what this affords that the organizing your application as a package doesn't.</li>
|
|
||||||
<li>Application Dispatching: The most powerful of the three! This is a slightly lower-level solution, wherein you actually run multiple applications concurrently, and dispatch requests to them. This is kind of overkill, but at least it's nice to know that it's possible - things like the <span class="url">async_app</span> example from previous could really make sense, if the app is large enough in scope. Application dispatching means you can just pull in another application and route things to it on the WSGI layer. Or something.</li>
|
|
||||||
</ul>
|
|
||||||
<p>Okay, but... how do they score up? I have some requirements:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>Organization</dt>
|
|
||||||
<dd>I want to define the behavior for <span class="url">example.com/articles/tamari/</span> in the same place as <span class="url">example.com/articles/language-for-games/</span> is defined, but in a different file from where <span class="url">example.com/games/hunt-the-wumpus</span> is defined.</dd>
|
|
||||||
<dt>Simplicity</dt>
|
|
||||||
<dd>Defining a URL route and endpoint for each subfolder of my application shouldn't be much more complicated than defining behaviors in a flat system. Ideally, registering all the behaviors for the <span class="url">articles/</span> subpath is no more complicated than <code>app.route("<span class="url">/articles/</span>", articles_handler)</code></dd>
|
|
||||||
<dt>Ease of Extension</dt>
|
|
||||||
<dd>I'm writing a family of pages. They're starting to get a little too complicated. It should be really easy to go from that situation to having a nicely-delineated subsection of my website.</dd>
|
|
||||||
<dt>Do I <em>Need</em> to Restart the Server?</dt>
|
|
||||||
<dd>I hate restarting the server. Maybe this is a little thing, but gah! I want the server to detect changes automatically! This shouldn't be that hard. Of course, this is a much thornier topic when it comes to subpages that might store their own state... So it might be out the window unless I want to get my hands <em>way</em> more dirty.</dd>
|
|
||||||
</dl>
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<table id="server-choices" class="span8 offset2">
|
|
||||||
<caption><h4>How do they fare up?</h4></caption>
|
|
||||||
<col><colgroup span=4></colgroup>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
|
|
||||||
<th>Organization</th>
|
|
||||||
<th>Simplicity</th>
|
|
||||||
<th>Ease of Extension</th>
|
|
||||||
<th>No Restart Required?</th>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Current</td>
|
|
||||||
|
|
||||||
<td class="label-warning"><i class="icon-question-sign"></i></td>
|
|
||||||
<td class="label-success"><i class="icon-ok-sign"></i></td>
|
|
||||||
<td class="label-important"><i class="icon-remove-sign"></i></td>
|
|
||||||
<td class="label-success"><i class="icon-ok-sign"></i></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Organize as a Package</td>
|
|
||||||
|
|
||||||
<td class="label-success"><i class="icon-ok-sign"></i></td>
|
|
||||||
<td class="label-warning"><i class="icon-question-sign"></i></td>
|
|
||||||
<td class="label-warning"><i class="icon-question-sign"></i></td>
|
|
||||||
<td class="label-important"><i class="icon-remove-sign"></i></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Blueprints</td>
|
|
||||||
|
|
||||||
<td class="label-success"><i class="icon-ok-sign"></i></td>
|
|
||||||
<td class="label-success"><i class="icon-ok-sign"></i></td>
|
|
||||||
<td class="label-success"><i class="icon-ok-sign"></i></td>
|
|
||||||
<td class="label-important"><i class="icon-remove-sign"></i></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Application Dispatch</td>
|
|
||||||
|
|
||||||
<td class="label-success"><i class="icon-ok-sign"></i></td>
|
|
||||||
<td class="label-important"><i class="icon-remove-sign"></i></td>
|
|
||||||
<td class="label-important"><i class="icon-remove-sign"></i></td>
|
|
||||||
<td class="label-important"><i class="icon-remove-sign"></i></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div></div>
|
|
||||||
<p>In light of this chart, it seems like Blueprints are the clear option. Also, "organize as package" is really vague. What they suggested didn't sound very helpful - but making python packages (finally learning how to use <span class="filename">__init__.py</span> files!) will probably get used in the solution I'm thinking I'll use, which looks something like this:</p>
|
|
||||||
<ul class="file-tree">
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">server/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-file"></i> <span class="filename">server.py</span></li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">articles/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-file"></i> <span class="filename">article_routing_blueprint.py</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">main_page.html</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">auriga.html</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">language-for-games.html</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">tamari.html</span></li>
|
|
||||||
<li><i class="icon-folder-close"></i> <span class="filename">tamari_files</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">games/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-file"></i> <span class="filename">games_blueprint.py</span></li>
|
|
||||||
<li><i class="icon-signal"></i> <span class="filename">scores.csv</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">play_the_game.html</span></li>
|
|
||||||
<li><i class="icon-align-left"></i> <span class="filename">game.js</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><i class="icon-folder-open"></i> <span class="filename">static/</span>
|
|
||||||
<ul>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">favicon.ico</span></li>
|
|
||||||
<li><i class="icon-eye-open"></i> <span class="filename">stylesheet.css</span></li>
|
|
||||||
<li><i class="icon-picture"></i> <span class="filename">lol_a_cat.jpg</span></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>If there's static content that is globally important, with simple routing rules, it can - of course - be stored in the server root's <span class="filename">static/</span> directory. Static file handlers don't take much configuration, so this can go in the root.</p>
|
|
||||||
<p>All the files related to articles are contained in the <span class="filename">articles/</span> directory, or subdirectories. <span class="filename">article_routing_blueprint.py</span> contains a blueprint definition that tells the server how to route calls that result in the rendering of the various articles I've written.</p>
|
|
||||||
<p>All files related to the little javascript games I've made, on the other hand, go in the <span class="filename">games/</span> directory. State for this application is managed by <span class="filename">games_blueprint.py</span>, which is sort of like a very tiny application. I think it's possible to keep track of state, if you remember to keep variables global... This is tricksy, but should be doable - and if it gets larger, it should almost certainly be developed as a separate application entirely. At that point, I should figure out how to include multiple applications in one website!</p>
|
|
||||||
<p>I want to finish this bit by writing down some code for the base <span class="filename">server.py</span> logic:</p>
|
|
||||||
<pre>
|
|
||||||
<code class="language-python">from flask import Flask
|
|
||||||
|
|
||||||
# app configuration and initialization
|
|
||||||
app = Flask(__name__)
|
|
||||||
app.debug = True
|
|
||||||
|
|
||||||
# content in <span class="filename">articles/</span>
|
|
||||||
import articles
|
|
||||||
app.register_blueprint(articles.blueprint)
|
|
||||||
|
|
||||||
# content in <span class="filename">games/</span>
|
|
||||||
import games
|
|
||||||
app.register_blueprint(games.blueprint, url_prefix="<span class="url">/games</span>")</code></pre>
|
|
||||||
<hr>
|
|
||||||
<h3>Okay, one last thing.</h3>
|
|
||||||
<p>This has been a lot about how to get some basic extensible functionality working. <i class="that-guy">But wait</i>, someone cries in the distance! <i class="that-guy">Why are we going to such lengths to do all this in the first place, when you're just serving static HTML files? Isn't this way more work than you need?</i><span class="sidenote span4">In case you're reading this article long after I've finished these changes (I hope so, 'cause I should get to work on this immediately), at this point all the articles were static HTML files. That voice speaks the truth.</span></p>
|
|
||||||
<p>Thanks for asking. The answer is that I want to change how this site is structured, and the articles are the specific thing I want to change. See, as it is, each article has basically the same header at the top, and basically the same footer at the bottom, and... Well, they're just all enclosed in the same stuff, and so when I change the styling of the website - or, horror of horrors, try to add a sidebar across the hwole site - I have to change all of them! And, as I think we've been over before, I'm <em>lazy</em>.</p>
|
|
||||||
<p>Conveniently, as I've been obsessively reading discussions of standards-compliant HTML5 and document formats and such lately, this laziness messes with my indomitable enthusiasm for conceptually pleasing solutions. Here's what I've got:</p>
|
|
||||||
<ul>
|
|
||||||
<li><b>Articles</b> on my site are blocks of text, consisting of my rambling on some topic. Something I've written down. They can have some amount of associated content, but for the most part they're just text. So, I'm going to reduce them down to their bare minimum of unique content - in many cases, just an <code language="html"><article></code> tag containing what I wrote!</li>
|
|
||||||
<li>But sometimes I want to have multiple articles display in one page! Sometimes my articles are single paragraphs. Sometimes they can be grouped into related, uh, groups! What do we do then? The answer is <strong>templates</strong>. Flask uses <a href="http://jinja.pocoo.org/">Jinja2</a>, a perfectly nice templating engine - and why not use it?</li>
|
|
||||||
<li>If I want to display the articles contained in <span class="filename">articles/parkour_is_awesome.html</span>, <span class="filename">articles/exercise.html</span>, and <span class="filename">articles/how_is_body.html</span>), then I just make a new page, a Jinja2 template, which contains this:
|
|
||||||
<pre>
|
|
||||||
<code class="language-jinja2"><!-- {% raw %} -->{% include "<span class="filename">articles/parkour_is_awesome.html</span>" %}
|
|
||||||
{% include "<span class="filename">articles/exercise.html</span>" %}
|
|
||||||
{% include "<span class="filename">articles/how_is_body.html</span>" %}<!-- {% endraw %} --></code></pre>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>And ta-da! We now have a page which has those three articles in a row.</p>
|
|
||||||
<p>This, of course, also means we have a neat format for how to display things in general. Someone requested access to a URL! Find the file it points to. If it's an HTML fragment, then point the <b>general page template</b> to that file, and render. The general page template is just a template that adds the header, footer, sidebar, universal styling, and so on, as required, for universality.</p>
|
|
||||||
<p>So if you go to <span class="url">example.com/tamari/</span>, the server says "Okay, you want to look at the article in the HTML fragment file <span class="filename">articles/tamari.html</span>." It renders the general page template around that article, and returns that to the user.</p>
|
|
||||||
<p>Because I like having the option to look at these things many ways, I'm probably also going to allow for a user to do <code class="language-bash">python articles.py --generate [path]</code>, which will simply spit out the the rendered results of going to <code class="language-bash">[path]</code>. I guess that <em>might</em> just be indistinguishable from using <code class="language-bash">wget</code>, but hey. It can't hurt to give more functionality!</p>
|
|
||||||
<p>It remains to be seen precisely how many pages on this site will use the general page template. I don't want to rely on it too much, but, man, is there <em>any</em> reason not to? Basically, it means that I don't have to worry about writing the headers of anything on my website. I guess I'll need to be able to throw it off when I'm making subpages that are intended to be stylistically distinct from the rest of my site.</p>
|
|
||||||
</article>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,35 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>This is a test</title>
|
|
||||||
<link href="/static/bootstrap/css/bootstrap.css" rel="stylesheet" type="text/css">
|
|
||||||
<link href="/static/shoofle.css" rel="stylesheet" type="text/css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<article class="project">
|
|
||||||
<h1>Distributed Speakers</h1>
|
|
||||||
<h4>(project idea)</h4>
|
|
||||||
<div class="important">
|
|
||||||
<p>So you want to have a rally. You want to hold a sports competition for your large neighborhood. Maybe you want to broadcast announcements across your company picnic. Maybe you want to throw an impromptu dance party!</p>
|
|
||||||
<p>The common line between all of these scenarios is this: you need a sound system, but you do not have one.</p>
|
|
||||||
</div>
|
|
||||||
<p>I first conceived of this while thinking about the specific issue of a dance party. Here's my solution:</p>
|
|
||||||
<ul>
|
|
||||||
<li>Everyone downloads this free app.</li>
|
|
||||||
<li>Everyone directs the app to the streaming media source of choice - a web radio station or something.</li>
|
|
||||||
<li>Each phone in the network listens to the audio it hears, and synchronizes what it's playing to the surroundings.</li>
|
|
||||||
</ul>
|
|
||||||
<p>I liked this idea because I have friends I like dancing with, but we rarely have a sound system set up and in place for dancing in public spaces. But anywhere you need to communicate something to a large number of people but you don't have a sound system, this app would be useful.</p>
|
|
||||||
<h3>Let's talk about issues.</h3>
|
|
||||||
<p class="important">How do you sync up a bunch of audio sources together on the fly, with limited communication between them?</p>
|
|
||||||
<p>That's the biggest problem, but there are smaller issues - well, they're really just the obstacles we'd need to face:</p>
|
|
||||||
<ul>
|
|
||||||
<li>How do we make this accept a wide variety of stream types - web radio, youtube, soundcloud, etc.?</li>
|
|
||||||
<li>How do you do ad hoc networking between mobile devices?</li>
|
|
||||||
<li>How do we tie this in with youtube playlists, which people will frequently want to play music from?</li>
|
|
||||||
<li>Is this even possible, when considering the speed-of-sound delay? How far apart can sources be, such that they're perceived as one sound rather than two?</li>
|
|
||||||
</ul>
|
|
||||||
</article>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -8,124 +8,96 @@
|
|||||||
<link href="/static/shoofle.css" rel="stylesheet" type="text/css">
|
<link href="/static/shoofle.css" rel="stylesheet" type="text/css">
|
||||||
<script src="/static/jquery.min.js" type="text/javascript"></script>
|
<script src="/static/jquery.min.js" type="text/javascript"></script>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
textarea {
|
body {
|
||||||
width: 100%;
|
background-color: gray;
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
#editor p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.block {
|
.block {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
.block.if {
|
.if-elseif-else-wrapper {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
background-color: rgb(200,200,255);
|
background-color: rgb(200,200,255);
|
||||||
}
|
}
|
||||||
.branch {
|
.branch {
|
||||||
|
margin-right: 4px;
|
||||||
background-color: rgb(200,255,200);
|
background-color: rgb(200,255,200);
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.block.while {
|
.while-wrapper {
|
||||||
background-color: rgb(255,200,200);
|
background-color: rgb(255,200,200);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="background-color: gray; margin: 1em;">
|
<body style="background-color: gray; margin: 1em;">
|
||||||
<div style="display: none;"></div>
|
<div class="block" id="editor" contentEditable>
|
||||||
|
<p class="code">some kind of preparation code, I guess</p>
|
||||||
|
<p class="code">or something</p>
|
||||||
When I see the text "if (something)", then I should make a new if block.
|
<div class="branch if">
|
||||||
|
<p class="condition">if (condition)</p>
|
||||||
["block", "block"] => ["block"]
|
<div class="block base">
|
||||||
["block", "block while"] => ["block", "block while"]
|
<p>do something in response to a true condition</p>
|
||||||
["block", "block if"] => ["block", "block if"]
|
</div>
|
||||||
<script type="text/javascript">
|
</div>
|
||||||
|
<div class="branch else-if">
|
||||||
|
<p class="condition">else if (some other condition)</p>
|
||||||
</script>
|
<div class="block base">
|
||||||
<style type="text/css">
|
<p>then we should do something specific else</p>
|
||||||
.block {display: block;}
|
</div>
|
||||||
.branch {display: inline-block;}
|
</div>
|
||||||
|
<div class="branch else">
|
||||||
</style>
|
<p class="condition">else</p>
|
||||||
<div class="block" id="editor" contentEditable>
|
<div class="block base">
|
||||||
<div class="block base" >
|
<p>some fallback thing!</p>
|
||||||
some kind of preparation code, I guess<br>
|
</div>
|
||||||
or something<br>
|
</div>
|
||||||
</div>
|
<p>some code</p>
|
||||||
<div class="block if">
|
<p>do other thing</p>
|
||||||
<div class="branch if">
|
<p>{} | : {} ();</p>
|
||||||
<div class="condition">if (condition)</div>
|
<div class="while-wrapper">
|
||||||
<div class="block base">do something in response to a true condition</div>
|
<p class="condition">while (something)</p>
|
||||||
|
<div class="block base">
|
||||||
|
<p>update the counters</p>
|
||||||
|
<p>hack the gibsons</p>
|
||||||
|
<p>do the stuff</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="branch else-if">
|
|
||||||
<div class="condition">else if (some other condition)</div>
|
|
||||||
<div class="block base">then we should do something specific else</div>
|
|
||||||
</div>
|
|
||||||
<div class="branch else">
|
|
||||||
<div class="condition">else</div>
|
|
||||||
<div class="block base">some fallback thing!</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="block base">
|
|
||||||
some code<br>
|
|
||||||
do other thing<br>
|
|
||||||
{} | : {} ();<br>
|
|
||||||
</div>
|
|
||||||
<div class="block while">
|
|
||||||
<div class="condition">while (something)</div>
|
|
||||||
<div class="block base">
|
|
||||||
update the counters<br>
|
|
||||||
hack the gibsons<br>
|
|
||||||
do the stuff<br>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr><hr>
|
|
||||||
<div></div>
|
|
||||||
<div class="block" style="width: 60em;">
|
|
||||||
<textarea></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<pre id="output" style="border: 1px solid black; width: 50%; background-color: rgb(200,200,255);"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
var finds_if_regex = /(?:\s*)(if\s*\([^)]+\)\s*)(\{[^}]*\})/;
|
var finds_if_regex = /(?:\s*)((?:else\s*)?if\s*\([^)]+\)\s*)\{([^}]*)\}/;
|
||||||
function make_new_if(c1, c2) {
|
function respond_to_ifs() {
|
||||||
var target;
|
var editor = $('#editor');
|
||||||
if (c1 == undefined) { target = $(this); }
|
|
||||||
if (c2 == undefined) { target = $(c1); }
|
|
||||||
else { target = $(c2); }
|
|
||||||
|
|
||||||
if (!target.is('.block.base')) {
|
var lines_of_code = editor.find('p');
|
||||||
target.find('.block.base').each(make_new_if);
|
lines_of_code.each(individual_line_if);
|
||||||
} else if (finds_if_regex.exec(target.html())) {
|
}
|
||||||
var contents = target.html();
|
function individual_line_if() {
|
||||||
var split_up = contents.split(finds_if_regex);
|
if (!finds_if_regex.exec($(this).text())) { return true; }
|
||||||
var new_blocks = [];
|
var split_up = $(this).text().split(finds_if_regex);
|
||||||
new_blocks.push($('<div></div>').append(split_up[0]).addClass('block base'));
|
|
||||||
for (var i=1; i<split_up.length; i+=3) {
|
var branch = $('<div></div>').addClass('branch if');
|
||||||
var if_container = $('<div></div>').addClass('block if');
|
$(this).before(branch);
|
||||||
var branch_container = $('<div></div>').addClass('branch if');
|
|
||||||
var conditional = $('<div></div>').addClass('condition').html(split_up[i]);
|
if (split_up[0].length > 0) {
|
||||||
var result = $('<div></div>').addClass('block base').html(split_up[i+1]);
|
branch.before($('<p></p>').text(split_up[0]));
|
||||||
branch_container.append(conditional);
|
}
|
||||||
branch_container.append(result);
|
|
||||||
if_container.append(branch_container);
|
branch.append($('<p class="condition"></p>').text(split_up[1]));
|
||||||
|
branch.append($('<div></div>').addClass('block').append($(this)));
|
||||||
new_blocks.push(if_container);
|
$(this).before('{');
|
||||||
if (split_up[i+2] != '') {
|
$(this).text(split_up[2]);
|
||||||
var post_if = $('<div></div>').addClass('block base').html(split_up[i+2]);
|
$(this).after('}');
|
||||||
new_blocks.push(post_if);
|
|
||||||
}
|
if (split_up[3].length > 0) {
|
||||||
}
|
branch.after($('<p></p>').text(split_up[2]));
|
||||||
target.after(new_blocks);
|
|
||||||
console.log(new_blocks);
|
|
||||||
target.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var finds_else_regex = /(?:[^\S])\s*else\s*(\{[^}]*\})/;
|
var finds_else_regex = /(?:[^\S])\s*else\s*(\{[^}]*\})/;
|
||||||
@ -139,32 +111,10 @@ function make_new_else(c1, c2) {
|
|||||||
target.find('.block.base')
|
target.find('.block.base')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var collapsible_block_selector = '.block.base';
|
|
||||||
var empty_text_regex = /\S/
|
|
||||||
var cbs = collapsible_block_selector;
|
|
||||||
function collapse_blocks(c1, c2) {
|
|
||||||
var target;
|
|
||||||
if (c1 == undefined) { target = $(this); }
|
|
||||||
if (c2 == undefined) { target = $(c1); }
|
|
||||||
else { target = $(c2); }
|
|
||||||
|
|
||||||
target.find('.block.base').filter(function() { return !empty_text_regex.exec($(this).text()); }).remove();
|
|
||||||
target.find('.block.base + .block.base').each(function () {
|
|
||||||
var base = $(this).prev('.block.base');
|
|
||||||
var new_base_contents = base.html() + '<br>' + $(this).html();
|
|
||||||
base.html(new_base_contents);
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
target.children().each(collapse_blocks);
|
|
||||||
}
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#editor').on('input', function() { make_new_if($(this)); });
|
$('#editor').on('input', function() { respond_to_ifs(); });
|
||||||
$('#editor').on('input', function() { collapse_blocks($(this)); });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user