Rendering working with rough initial content

This commit is contained in:
Thomas Karpiniec 2016-01-22 23:39:34 +11:00
commit 70b546bcee
18 changed files with 5784 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
rendered/
*~

3
configs/admin.config.php Normal file
View File

@ -0,0 +1,3 @@
<?php
?>

33
configs/user.config.php Normal file
View File

@ -0,0 +1,33 @@
<?php
// Basic configuration
// Title of manual, to appear in header and page title
$config["title"] = "User Guide";
// Directory (relative to render.php) where html pages are located
$config["html_dir"] = "html/user";
// Directory (relative to render.php) where static resources are located
$config["resources_dir"] = "resources/user";
// Name of subdirectory in the output where used resources are placed
$config["resources_output_dir"] = "res_user";
// Where rendered output is placed
$config["output_dir"] = "rendered/user";
// Page listing
// These must be specified in the order you want them to appear
// id - If "foo" will look for "foo.html"
// title - Used in the table of contents and {PAGE_TITLE:foo} substitutions
$config["pages"] = array(
array("id" => "what_is_gnu_social", "title" => "What is GNU social"),
array("id" => "getting_started", "title" => "Getting Started")
);
?>

14
html/common/footer.html Normal file
View File

@ -0,0 +1,14 @@
<div class="spacer"></div>
<div class="navigation">
<div class="left"><a href="{PREV_URL}">{PREV_TITLE}</a></div>
<div class="right"><a href="{NEXT_URL}">{NEXT_TITLE}</a></div>
<div class="centre"><a href="{TOC_URL}">{TOC_TITLE}</a></div>
</div>
<hr />
<div class="footer">
<div class="left">Generated {TIMESTAMP}</div> <div class="right">Revision: {GIT_REV_ID}</div>
</div>
</div>
</body>
</html>

18
html/common/header.html Normal file
View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{TITLE} - GNU social</title>
<link rel="stylesheet" href="{RES:manual-style.css}">
</head>
<body><div class="contents">
<div class="heading">
<img src="{RES:logo.png}" width="175" height="55" />
<h1>{TITLE}</h1>
</div>
<div class="navigation">
<div class="left"><a href="{PREV_URL}">{PREV_TITLE}</a></div>
<div class="right"><a href="{NEXT_URL}">{NEXT_TITLE}</a></div>
<div class="centre"><a href="{TOC_URL}">{TOC_TITLE}</a></div>
</div>

1
html/common/toc-h1.html Normal file
View File

@ -0,0 +1 @@
<div class="toc-h1"><a href="{TOC_ENTRY_PAGE}#{TOC_ENTRY_SECTION}">{TOC_ENTRY_NUMBER} {TOC_ENTRY_TITLE}</a></div>

1
html/common/toc-h2.html Normal file
View File

@ -0,0 +1 @@
<div class="toc-h2"><a href="{TOC_ENTRY_PAGE}#{TOC_ENTRY_SECTION}">{TOC_ENTRY_NUMBER} {TOC_ENTRY_TITLE}</a></div>

1
html/common/toc-h3.html Normal file
View File

@ -0,0 +1 @@
<div class="toc-h3"><a href="{TOC_ENTRY_PAGE}#{TOC_ENTRY_SECTION}">{TOC_ENTRY_NUMBER} {TOC_ENTRY_TITLE}</a></div>

2
html/common/toc.html Normal file
View File

@ -0,0 +1,2 @@
<h2>Contents</h2>

View File

@ -0,0 +1,86 @@
{HEADING:SECTION:choosing_a_server:Choosing a server}
<p>You have to make one decision to get on GNU social: which server to use. If you're technically inclined and want to host your own server then you can do that. For everyone else there are many choices available. Many of them are listed on <a href="http://www.skilledtests.com/wiki/List_of_Independent_Statusnet_Instances">this webpage</a>.</p>
<p>If you don't want to shop around, here are some popular choices particularly for English speakers:</p>
<ul>
<li><a href="https://quitter.se/">https://quitter.se/</a></li>
<li><a href="https://loadaverage.org/">https://loadaverage.org/</a></li>
<li><a href="https://quitter.no/">https://quitter.no/</a></li>
</ul>
<p>Otherwise you might like to use a server with people you already know. Each server has a section where you can see all the notices published on that server. If you choose a server that's relevant to you this could be a good way to find people you already know or meet new people who share similar interests.</p>
<p>Although there are many GNU social servers not all of them allow the general public to create accounts. This is a choice for the administrator of a particular server.</p>
{HEADING:SECTION:registering:Registering an account}
<p>In this example we will use <a href="https://quitter.no">quitter.no</a>, which allows new users to register freely. This server looks very similar to Twitter because it is using a plugin called Qvitter. It has a "Sign Up" section on the bottom-left of the home page. Enter your basic information and click "Sign up to Quitter.no":</p>
<p>[main screenshot with sign up section marked]</p>
<p>Once you click the button you will be prompted for more information:<p>
<p>[details]</p>
<p>Your nickname is the main name for your account, so choose carefully. This is allowed to contain only letters and numbers. You can also set a "Full name", which is more flexible, but feel free to choose a pseudonym or nickname here if you like.</p>
<p>A real email address is required for confirmation. This is normally needed to prevent spam.</p>
<p>Choose a good password. As always it is a good idea to use a password that you don't use anywhere else. Free software like <a href="https://www.keepassx.org/">KeePassX</a> can help you generate and remember your passwords.</p>
<p>Once you confirm your email address you have an account. Congratulations!</p>
<p>Note that when you tell other people about your account you have to specify both the nickname and the server where you registered. It looks like an email address. For example: myaccountnickname@quitter.no</p>
{HEADING:SECTION:publishing:Publishing a notice}
<p>Depending on which server you're using you might see something different once you log in. Here are two examples:</p>
<p>[screenshot 1] [screenshot 2]</p>
<p>In both cases you have a text box to type a message. Click inside it, type a notice, then click "Send" to publish it to your followers.</p>
{HEADING:SECTION:exploring:Exploring the network}
<p>Once you have an account you need to find some interesting people to follow. If somebody you know is already using GNU social, ask them for the URL of their profile. You can put it straight into your web browser to see their notices. If you would like to follow them, see the next section.</p>
<p>If you don't know anyone there are several different ways to explore to explore the GNU social network. Look for these links:</p>
<ul>
<li><em>Public</em> / <em>Public Timeline</em>: This shows you all of the notices published on this server.</li>
<li><em>Network</em> / <em>The Whole Known Network</em> - This shows you all of the noticed published on this server, plus all of the notices of all the people followed by people on this server. This is a good way to see lots of activity if you are on a busy server.</li>
</ul>
<p>You can look up GNU social servers in other ways, such as searching in search engines. If you find another server you can follow any user who has an account there, whether or not they are already part of the "known network" for your server.</p>
{HEADING:SECTION:following:Following other people}
<p>When you follow somebody it means their notices will appear in your timeline (or Home screen). The simplest way to follow somebody is to visit their profile. For example, if you are browsing "The Whole Known Network" you could click on an account you see there.</p>
<p>[example]</p>
<p>Once the account page loads you will see some option to "Remote follow". Depending on the style of the website this could take multiple forms:</p>
<p>[form 1] [form 2] [form 3]</p>
<p>When you click on the button you will be asked for your account address. This is the full form that looks like an email address; something like: myaccountname@someserver.com</p>
<p>After you submit your account, you will be taken to a page where you confirm the nickname of the person you wish to follow, along with your account. Click "XXX".</p>
<p>You will then be redirected to the server where your accounted is hosted. It will also ask you to confirm that you wish to follow this person. Click "Confirm".</p>
<p>Congratulations! You are now following that person.</p>
<p>If you click on the "Home" / "Timeline" link on your server, you will see notices that they post from now on. (Not previous ones.)</p>
<p>[screenshot]</p>

View File

@ -0,0 +1,21 @@
{HEADING:SECTION:what_is_gnu_social:What is GNU social}
<p>GNU social is a social network for microblogging. It enables you to publish short notices including URLs and pictures. If you're interested in what someone has to say you can <i>follow</i> them. When you log in to your account you see a timeline containing all of the notices from people that you follow. You can have a conversation with another person by replying to each other's notices.</p>
<a href="{RES:gnusocialno_general.png}">
<img src="{RES:gnusocialno_general_small.png}" alt="Homepage of gnusocial.no" class="figure" />
</a>
<p>You may have seen this sort of thing before. GNU social is special for two main reasons: it's <em>decentralised</em>, and it's <em>free software</em>.</p>
<p>Being decentralised means that there is no single server that controls GNU social. Instead, many servers are run by different people around the world. These servers communicate with each other to form a <i>federation</i>. You can create an account on any one of them. Although the servers sometimes look different, ultimately it doesn't matter which one you choose&mdash;you're still part of the same network as everyone else.</p>
<img src="{RES:federation.png}" alt="Diagram of federated servers" class="figure" />
<p>If one server suffers an outage it's inconvenient for the people who have an account on that particular server but the rest of the network continues to operate as normal. This makes GNU social highly resilient. Censorship is difficult as servers can be located anywhere in the world.</p>
<p>Because GNU social is free software it's here to stay. A corporate social network might disappear or start running advertisements when the venture capital runs out. The GNU social code is available to everybody and there are many servers where it's free to create an account.</p>
<p>This is a social network that does what's best for the people who use it&mdash;not what makes the most money. Jump ahead to {LINK:exploring}</p>

214
render.php Normal file
View File

@ -0,0 +1,214 @@
<?php
// This is pretty bad code. Sorry. I will clean it up.
foreach (glob("configs/*.php") as $config_file) {
if (is_file($config_file)) {
echo "Processing render configuration $config_file\n";
render_with_config_path($config_file);
}
}
function render_with_config_path($config_file) {
$config = array();
include($config_file);
if (!isset($config["pages"])) {
echo "Not a valid configuration; skipping\n";
return;
}
// Prepare substitutions
$substitutions = array("{TITLE}" => $config["title"]);
$rev_id = exec("git rev-parse --short HEAD", $output, $retval);
if ($retval != 0) {
$rev_id = "unknown";
}
$substitutions["{GIT_REV_ID}"] = $rev_id;
date_default_timezone_set('UTC');
$substitutions["{TIMESTAMP}"] = date("Y-m-d H:i:s e");
// Copy resources across
$resources_to_copy = array_merge(glob("resources/common/*"), glob($config["resources_dir"] . "/*"));
$res_out_dir = $config["output_dir"] . "/" . $config["resources_output_dir"];
if (!is_dir($res_out_dir)) {
mkdir($res_out_dir, 0777, true);
}
foreach ($resources_to_copy as $res) {
$res_name = basename($res);
$substitutions["{RES:$res_name}"] = $config["resources_output_dir"] . "/$res_name";
copy($res, "$res_out_dir/$res_name");
}
if (!is_dir($config["output_dir"])) {
mkdir($config["output_dir"], 0777, true);
}
// We need to pre-process all the pages to get the section headings ready
$sections = array(); // entries are associative arrays
$template_texts = array();
$page_no = 1;
foreach ($config["pages"] as $page) {
// Read in the text
$template_html = $config["html_dir"] . "/" . $page["id"] . ".html";
$text = file_get_contents($template_html);
$section_no = 0;
$subsection_no = 0;
// Look for things we need to convert to h1, h2, h3
preg_match_all("/{HEADING:(PAGE|SECTION|SUBSECTION):([^:]*):([^}]+)}/", $text, $section_matches);
$originals = $section_matches[0];
$types = $section_matches[1];
$ids = $section_matches[2];
$titles = $section_matches[3];
// TOC gets its info from the config file, not from an h1 which may or may not be present
$page_id = $page["id"];
$sections[] = array("type" => "PAGE", "page" => "$page_id.html", "section" => "", "number" => "$page_no.", "title" => $page["title"]);
for ($i = 0; $i < count($types); $i++) {
$tag = "h1";
$number = "$page_no.";
if ($types[$i] == "SECTION") {
$tag = "h2";
$section_no++;
$number = "$page_no.$section_no.";
}
if ($types[$i] == "SUBSECTION") {
$tag = "h3";
$subsection_no++;
$number = "$page_no.$section_no.$subsection_no.";
}
// If we have an ID
$anchor_start = "";
$anchor_end = "";
if (strlen($ids[$i]) > 0 && $types[$i] != "PAGE") { // pages are always added the TOC and have empty section_id
// Add it to the TOC array
$sections[] = array("type" => $types[$i], "page" => "$page_id.html", "section" => $ids[$i], "number" => $number, "title" => $titles[$i]);
// Also create an internal anchor
$anchor_start = "<a name=\"$ids[$i]\">";
$anchor_end = "</a>";
}
$final_tag = "<$tag>$anchor_start$number $titles[$i]$anchor_end</$tag>";
// Replace the template with the tag
$text = str_replace($originals[$i], $final_tag, $text);
// Now create substitutions for this tag so other pages can refer to them
$page_id = $page["id"];
$section_id = $ids[$i];
$title = $titles[$i];
$substitutions["{LINK:$section_id}"] = "<a href=\"$page_id.html#$section_id\">$title</a>";
$substitutions["{TITLE:$section_id}"] = $title;
}
// Save the text for later
$template_texts[$page["id"]] = $text;
$page_no++;
}
// Render each page
for ($i = 0; $i < count($config["pages"]); $i++) {
$page = $config["pages"][$i];
// Configure page-specific substitutions
$substitutions["{PREV_URL}"] = "";
$substitutions["{PREV_TITLE}"] = "";
$substitutions["{NEXT_URL}"] = "";
$substitutions["{NEXT_TITLE}"] = "";
$substitutions["{TOC_URL}"] = "index.html";
$substitutions["{TOC_TITLE}"] = "Contents";
if (isset($config["pages"][$i-1])) {
$prev_page = $config["pages"][$i-1];
$substitutions["{PREV_URL}"] = $prev_page["id"] . ".html";
$substitutions["{PREV_TITLE}"] = $prev_page["title"];
}
if (isset($config["pages"][$i+1])) {
$next_page = $config["pages"][$i+1];
$substitutions["{NEXT_URL}"] = $next_page["id"] . ".html";
$substitutions["{NEXT_TITLE}"] = $next_page["title"];
}
$template_html = $config["html_dir"] . "/" . $page["id"] . ".html";
$out_html = $config["output_dir"] . "/" . $page["id"] . ".html";
if (is_file($out_html)) {
unlink($out_html);
}
append_file_and_sub($out_html, "html/common/header.html", $substitutions);
$text = do_substitutions($template_texts[$page["id"]], $substitutions);
file_put_contents($out_html, $text, FILE_APPEND);
append_file_and_sub($out_html, "html/common/footer.html", $substitutions);
}
// Render the index / TOC now that we have all the information at hand
$toc_html = $config["output_dir"] . "/index.html";
$toc_text = file_get_contents("html/common/toc.html");
$toc_h1 = file_get_contents("html/common/toc-h1.html");
$toc_h2 = file_get_contents("html/common/toc-h2.html");
$toc_h3 = file_get_contents("html/common/toc-h3.html");
foreach ($sections as $section) {
$start = $toc_h1;
if ($section["type"] == "SECTION") $start = $toc_h2;
if ($section["type"] == "SUBSECTION") $start = $toc_h3;
$toc_subs["{TOC_ENTRY_NUMBER}"] = $section["number"];
$toc_subs["{TOC_ENTRY_TITLE}"] = $section["title"];
$toc_subs["{TOC_ENTRY_PAGE}"] = $section["page"];
$toc_subs["{TOC_ENTRY_SECTION}"] = $section["section"];
$line = do_substitutions($start, $toc_subs);
$toc_text .= "$line\n";
}
$substitutions["{PREV_URL}"] = "";
$substitutions["{PREV_TITLE}"] = "";
$substitutions["{NEXT_URL}"] = $config["pages"][0]["id"] . ".html";
$substitutions["{NEXT_TITLE}"] = $config["pages"][0]["title"];
// Write it to disk
if (is_file($toc_html)) {
unlink($toc_html);
}
append_file_and_sub($toc_html, "html/common/header.html", $substitutions);
file_put_contents($toc_html, $toc_text, FILE_APPEND);
append_file_and_sub($toc_html, "html/common/footer.html", $substitutions);
// This manual is all done
}
function append_file_and_sub($dest, $src, $substitutions) {
// Read in starting text
$text = file_get_contents($src);
$text = do_substitutions($text, $substitutions);
// Append processed text to the destination file
touch($dest);
file_put_contents($dest, $text, FILE_APPEND);
}
function do_substitutions($text, $substitutions) {
// Perform all template substitutions
foreach ($substitutions as $from => $to) {
$text = str_replace($from, $to, $text);
}
return $text;
}
?>

BIN
resources/common/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,103 @@
body {
background-color: #E9EAED;
font-family: serif;
}
div.contents {
background-color: white;
max-width: 50em;
margin-left: auto;
margin-right: auto;
padding-left: 3em;
padding-right: 3em;
padding-top: 1em;
padding-bottom: 2em;
margin-top: 1em;
}
h1, h2, h3 {
font-family: sans-serif;
}
h1 {
margin-top: 0;
}
h2 {
border-bottom: 1px solid black;
font-weight: normal;
}
div.heading {
text-align: center;
}
div.footer {
font-size: smaller;
font-style: italic;
width: 70%;
margin-left: auto;
margin-right: auto;
}
.left {
float: left;
}
.right {
float: right;
}
.navigation {
text-align: center;
margin-bottom: 1em;
font-size: small;
font-family: sans-serif;
}
.navigation .left {
width: 33%;
text-align: left;
}
.navigation .centre {
margin-left: auto;
margin-right: auto;
width: 33%;
}
.navigation .right {
width: 33%;
text-align: right;
}
img.figure {
display: block;
margin-left: auto;
margin-right: auto;
border: 0;
}
hr {
border: 0 none;
height: 1px;
color: black;
background-color: black;
}
.toc-h1 {
padding-top: 0.5em;
text-transform: uppercase;
}
.toc-h2 {
margin-left: 4em;
}
.toc-h3 {
margin-left: 8em;
}
.spacer {
height: 1em;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB