Refactor for new page structure

This commit is contained in:
Tim Van Baak 2018-10-28 13:50:58 -07:00
parent 25a674121f
commit df22907a41
4 changed files with 206 additions and 149 deletions

View File

@ -153,7 +153,7 @@ class LexiconArticle:
article_by_title[target].citedby.add(article.title) article_by_title[target].citedby.add(article.title)
return list(article_by_title.values()) return list(article_by_title.values())
def build_default_content(self): def build_default_contentblock(self):
""" """
Formats citations into the article content as normal HTML links Formats citations into the article content as normal HTML links
and returns the result. and returns the result.
@ -164,23 +164,29 @@ class LexiconArticle:
"" if cite_tuple[1] in self.wcites else " class=\"phantom\"") "" if cite_tuple[1] in self.wcites else " class=\"phantom\"")
for format_id, cite_tuple in self.citations.items() for format_id, cite_tuple in self.citations.items()
} }
return self.content.format(**format_map) article_content = self.content.format(**format_map)
return "<div class=\"contentblock\">\n<h1>{}</h1>\n{}</div>\n".format(
self.title,
article_content)
def build_default_citeblock(self, prev_article, next_article): def build_default_citeblock(self, prev_article, next_article):
""" """
Builds the citeblock content HTML for use in regular article pages. Builds the citeblock content HTML for use in regular article pages.
For each defined target, links the target page as Previous or Next. For each defined target, links the target page as Previous or Next.
""" """
citeblock = "<div class=\"content citeblock\">\n" citeblock = "<div class=\"contentblock citeblock\">\n"
# Prev/next links # Prev/next links:
if next_article is not None: if next_article is not None or prev_article is not None:
citeblock += "<p style=\"float:right\"><a href=\"{}.html\"{}>Next &#8594;</a></p>\n".format( prev_link = ("<a href=\"{}.html\"{}>&#8592; Previous</a>".format(
next_article.title_filesafe, " class=\"phantom\"" if next_article.player is None else "") prev_article.title_filesafe,
if prev_article is not None: " class=\"phantom\"" if prev_article.player is None else "")
citeblock += "<p><a href=\"{}.html\"{}>&#8592; Previous</a></p>\n".format( if prev_article is not None else "")
prev_article.title_filesafe, " class=\"phantom\"" if prev_article.player is None else "") next_link = ("<a href=\"{}.html\"{}>Next &#8594;</a>".format(
if next_article is None and prev_article is None: next_article.title_filesafe,
citeblock += "<p>&nbsp;</p>\n" " class=\"phantom\"" if next_article.player is None else "")
if next_article is not None else "")
citeblock += "<table><tr>\n<td>{}</td>\n<td>{}</td>\n</table></tr>\n".format(
prev_link, next_link)
# Citations # Citations
cites_links = [ cites_links = [
"<a href=\"{1}.html\"{2}>{0}</a>".format( "<a href=\"{1}.html\"{2}>{0}</a>".format(
@ -189,7 +195,7 @@ class LexiconArticle:
for title in sorted( for title in sorted(
self.wcites | self.pcites, self.wcites | self.pcites,
key=lambda t: utils.titlesort(t))] key=lambda t: utils.titlesort(t))]
cites_str = " | ".join(cites_links) cites_str = " / ".join(cites_links)
if len(cites_str) < 1: cites_str = "&mdash;" if len(cites_str) < 1: cites_str = "&mdash;"
citeblock += "<p>Citations: {}</p>\n".format(cites_str) citeblock += "<p>Citations: {}</p>\n".format(cites_str)
# Citedby # Citedby
@ -199,7 +205,7 @@ class LexiconArticle:
for title in sorted( for title in sorted(
self.citedby, self.citedby,
key=lambda t: utils.titlesort(t))] key=lambda t: utils.titlesort(t))]
citedby_str = " | ".join(citedby_links) citedby_str = " / ".join(citedby_links)
if len(citedby_str) < 1: citedby_str = "&mdash;" if len(citedby_str) < 1: citedby_str = "&mdash;"
citeblock += "<p>Cited by: {}</p>\n</div>\n".format(citedby_str) citeblock += "<p>Cited by: {}</p>\n</div>\n".format(citedby_str)
return citeblock return citeblock

View File

@ -8,17 +8,37 @@ from collections import defaultdict # For rank inversion in statistics
from src import utils from src import utils
from src.article import LexiconArticle from src.article import LexiconArticle
def build_contents_page(articles, config): class LexiconPage:
"""
An abstraction layer around formatting a Lexicon page skeleton with kwargs
so that kwargs that are constant across pages aren't repeated.
"""
def __init__(self, skeleton=None, page=None):
self.kwargs = {}
self.skeleton = skeleton
if page is not None:
self.skeleton = page.skeleton
self.kwargs = dict(page.kwargs)
def add_kwargs(self, **kwargs):
self.kwargs.update(kwargs)
def format(self, **kwargs):
total_kwargs = {**self.kwargs, **kwargs}
return self.skeleton.format(**total_kwargs)
def build_contents_page(page, articles, index_list):
""" """
Builds the full HTML of the contents page. Builds the full HTML of the contents page.
""" """
content = "" content = "<div class=\"contentblock\">"
# Head the contents page with counts of written and phantom articles # Head the contents page with counts of written and phantom articles
phantom_count = len([article for article in articles if article.player is None]) phantom_count = len([article for article in articles if article.player is None])
if phantom_count == 0: if phantom_count == 0:
content = "<p>There are <b>{0}</b> entries in this lexicon.</p>\n".format(len(articles)) content += "<p>There are <b>{0}</b> entries in this lexicon.</p>\n".format(len(articles))
else: else:
content = "<p>There are <b>{0}</b> entries, <b>{1}</b> written and <b>{2}</b> phantom.</p>\n".format( content += "<p>There are <b>{0}</b> entries, <b>{1}</b> written and <b>{2}</b> phantom.</p>\n".format(
len(articles), len(articles) - phantom_count, phantom_count) len(articles), len(articles) - phantom_count, phantom_count)
# Prepare article links # Prepare article links
link_by_title = {article.title : "<a href=\"../article/{1}.html\"{2}>{0}</a>".format( link_by_title = {article.title : "<a href=\"../article/{1}.html\"{2}>{0}</a>".format(
@ -28,7 +48,7 @@ def build_contents_page(articles, config):
# Write the articles in alphabetical order # Write the articles in alphabetical order
content += utils.load_resource("contents.html") content += utils.load_resource("contents.html")
content += "<div id=\"index-order\" style=\"display:none\">\n<ul>\n" content += "<div id=\"index-order\" style=\"display:none\">\n<ul>\n"
indices = config["INDEX_LIST"].split("\n") indices = index_list.split("\n")
alphabetical_order = sorted( alphabetical_order = sorted(
articles, articles,
key=lambda a: utils.titlesort(a.title)) key=lambda a: utils.titlesort(a.title))
@ -64,70 +84,31 @@ def build_contents_page(articles, config):
content += "<li>{}</li>\n".format(link_by_title[article.title]) content += "<li>{}</li>\n".format(link_by_title[article.title])
content += "</ul>\n</div>\n" content += "</ul>\n</div>\n"
# Fill in the page skeleton # Fill in the page skeleton
entry_skeleton = utils.load_resource("entry-page.html") return page.format(title="Index", content=content)
css = utils.load_resource("lexicon.css")
return entry_skeleton.format(
title="Index of " + config["LEXICON_TITLE"],
lexicon=config["LEXICON_TITLE"],
css=css,
logo=config["LOGO_FILENAME"],
prompt=config["PROMPT"],
sort=config["DEFAULT_SORT"],
content=content,
citeblock="")
def build_rules_page(config): def build_rules_page(page):
""" """
Builds the full HTML of the rules page. Builds the full HTML of the rules page.
""" """
content = utils.load_resource("rules.html") content = utils.load_resource("rules.html")
# Fill in the entry skeleton # Fill in the entry skeleton
entry_skeleton = utils.load_resource("entry-page.html") return page.format(title="Rules", content=content)
css = utils.load_resource("lexicon.css")
return entry_skeleton.format(
title="Rules",
lexicon=config["LEXICON_TITLE"],
css=css,
logo=config["LOGO_FILENAME"],
prompt=config["PROMPT"],
sort=config["DEFAULT_SORT"],
content=content,
citeblock="")
def build_formatting_page(config): def build_formatting_page(page):
""" """
Builds the full HTML of the formatting page. Builds the full HTML of the formatting page.
""" """
content = utils.load_resource("formatting.html") content = utils.load_resource("formatting.html")
# Fill in the entry skeleton # Fill in the entry skeleton
entry_skeleton = utils.load_resource("entry-page.html") return page.format(title="Formatting", content=content)
css = utils.load_resource("lexicon.css")
return entry_skeleton.format(
title="Formatting",
lexicon=config["LEXICON_TITLE"],
css=css,
logo=config["LOGO_FILENAME"],
prompt=config["PROMPT"],
sort=config["DEFAULT_SORT"],
content=content,
citeblock="")
def build_session_page(config): def build_session_page(page, session_content):
""" """
Builds the full HTML of the session page. Builds the full HTML of the session page.
""" """
# Fill in the entry skeleton # Fill in the entry skeleton
entry_skeleton = utils.load_resource("entry-page.html") content = "<div class=\"contentblock\">{}</div>".format(session_content)
css = utils.load_resource("lexicon.css") return page.format(title="Session", content=content)
return entry_skeleton.format(
title=config["LEXICON_TITLE"],
lexicon=config["LEXICON_TITLE"],
css=css,
logo=config["LOGO_FILENAME"],
prompt=config["PROMPT"],
sort=config["DEFAULT_SORT"],
content=config["SESSION_PAGE"],
citeblock="")
def reverse_statistics_dict(stats, reverse=True): def reverse_statistics_dict(stats, reverse=True):
""" """
@ -147,7 +128,7 @@ def reverse_statistics_dict(stats, reverse=True):
def itemize(stats_list): def itemize(stats_list):
return map(lambda x: "{0} &ndash; {1}".format(x[0], "; ".join(x[1])), stats_list) return map(lambda x: "{0} &ndash; {1}".format(x[0], "; ".join(x[1])), stats_list)
def build_statistics_page(articles, config): def build_statistics_page(page, articles):
""" """
Builds the full HTML of the statistics page. Builds the full HTML of the statistics page.
""" """
@ -174,19 +155,19 @@ def build_statistics_page(articles, config):
# Format the ranks into strings # Format the ranks into strings
top_ranked_items = itemize(top_ranked) top_ranked_items = itemize(top_ranked)
# Write the statistics to the page # Write the statistics to the page
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Top 10 pages by page rank:</u><br>\n" content += "<u>Top 10 pages by page rank:</u><br>\n"
content += "<br>\n".join(top_ranked_items) content += "<br>\n".join(top_ranked_items)
content += "</p>\n</div>\n" content += "</div>\n"
# Top number of citations made # Top number of citations made
citations_made = { title : len(cites) for title, cites in cite_map.items() } citations_made = { title : len(cites) for title, cites in cite_map.items() }
top_citations = reverse_statistics_dict(citations_made)[:3] top_citations = reverse_statistics_dict(citations_made)[:3]
top_citations_items = itemize(top_citations) top_citations_items = itemize(top_citations)
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Most citations made from:</u><br>\n" content += "<u>Most citations made from:</u><br>\n"
content += "<br>\n".join(top_citations_items) content += "<br>\n".join(top_citations_items)
content += "</p>\n</div>\n" content += "</div>\n"
# Top number of times cited # Top number of times cited
# Build a map of what cites each article # Build a map of what cites each article
@ -201,10 +182,10 @@ def build_statistics_page(articles, config):
citations_to = { title : len(cites) for title, cites in cited_by_map.items() } citations_to = { title : len(cites) for title, cites in cited_by_map.items() }
top_cited = reverse_statistics_dict(citations_to)[:3] top_cited = reverse_statistics_dict(citations_to)[:3]
top_cited_items = itemize(top_cited) top_cited_items = itemize(top_cited)
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Most citations made to:</u><br>\n" content += "<u>Most citations made to:</u><br>\n"
content += "<br>\n".join(top_cited_items) content += "<br>\n".join(top_cited_items)
content += "</p>\n</div>\n" content += "</div>\n"
# Top article length, roughly by words # Top article length, roughly by words
article_length = {} article_length = {}
@ -218,16 +199,16 @@ def build_statistics_page(articles, config):
article_length[article.title] = wordcount article_length[article.title] = wordcount
top_length = reverse_statistics_dict(article_length)[:3] top_length = reverse_statistics_dict(article_length)[:3]
top_length_items = itemize(top_length) top_length_items = itemize(top_length)
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Longest article:</u><br>\n" content += "<u>Longest article:</u><br>\n"
content += "<br>\n".join(top_length_items) content += "<br>\n".join(top_length_items)
content += "</p>\n</div>\n" content += "</div>\n"
# Total word count # Total word count
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Total word count:</u><br>\n" content += "<u>Total word count:</u><br>\n"
content += str(sum(article_length.values())) + "</p>" content += str(sum(article_length.values()))
content += "</p>\n</div>\n" content += "</div>\n"
# Player pageranks # Player pageranks
players = sorted(set([article.player for article in articles if article.player is not None])) players = sorted(set([article.player for article in articles if article.player is not None]))
@ -247,10 +228,10 @@ def build_statistics_page(articles, config):
in articles_by_player.items()} in articles_by_player.items()}
player_rank = reverse_statistics_dict(pagerank_by_player) player_rank = reverse_statistics_dict(pagerank_by_player)
player_rank_items = itemize(player_rank) player_rank_items = itemize(player_rank)
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Player total page rank:</u><br>\n" content += "<u>Player total page rank:</u><br>\n"
content += "<br>\n".join(player_rank_items) content += "<br>\n".join(player_rank_items)
content += "</p>\n</div>\n" content += "</div>\n"
# Player citations made # Player citations made
player_cite_count = { player_cite_count = {
@ -258,10 +239,10 @@ def build_statistics_page(articles, config):
for player, articles in articles_by_player.items()} for player, articles in articles_by_player.items()}
player_cites_made_ranks = reverse_statistics_dict(player_cite_count) player_cites_made_ranks = reverse_statistics_dict(player_cite_count)
player_cites_made_items = itemize(player_cites_made_ranks) player_cites_made_items = itemize(player_cites_made_ranks)
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Citations made by player</u><br>\n" content += "<u>Citations made by player</u><br>\n"
content += "<br>\n".join(player_cites_made_items) content += "<br>\n".join(player_cites_made_items)
content += "</p>\n</div>\n" content += "</div>\n"
# Player cited count # Player cited count
cited_times = {player : 0 for player in players} cited_times = {player : 0 for player in players}
@ -270,23 +251,13 @@ def build_statistics_page(articles, config):
cited_times[article.player] += len(article.citedby) cited_times[article.player] += len(article.citedby)
cited_times_ranked = reverse_statistics_dict(cited_times) cited_times_ranked = reverse_statistics_dict(cited_times)
cited_times_items = itemize(cited_times_ranked) cited_times_items = itemize(cited_times_ranked)
content += "<div class=\"moveable\">\n" content += "<div class=\"contentblock\">\n"
content += "<p><u>Citations made to player</u><br>\n" content += "<u>Citations made to player</u><br>\n"
content += "<br>\n".join(cited_times_items) content += "<br>\n".join(cited_times_items)
content += "</p>\n</div>\n" content += "</div>\n"
# Fill in the entry skeleton # Fill in the entry skeleton
entry_skeleton = utils.load_resource("entry-page.html") return page.format(title="Statistics", content=content)
css = utils.load_resource("lexicon.css")
return entry_skeleton.format(
title="Statistics",
lexicon=config["LEXICON_TITLE"],
css=css,
logo=config["LOGO_FILENAME"],
prompt=config["PROMPT"],
sort=config["DEFAULT_SORT"],
content=content,
citeblock="")
def build_graphviz_file(cite_map): def build_graphviz_file(cite_map):
""" """
@ -367,26 +338,29 @@ def build_all(path_prefix, lexicon_name):
lex_path = os.path.join(path_prefix, lexicon_name) lex_path = os.path.join(path_prefix, lexicon_name)
# Load the Lexicon's peripherals # Load the Lexicon's peripherals
config = utils.load_config(lexicon_name) config = utils.load_config(lexicon_name)
entry_skeleton = utils.load_resource("entry-page.html") page_skeleton = utils.load_resource("page-skeleton.html")
css = utils.load_resource("lexicon.css") page = LexiconPage(skeleton=page_skeleton)
page.add_kwargs(
lexicon=config["LEXICON_TITLE"],
logo=config["LOGO_FILENAME"],
prompt=config["PROMPT"],
sort=config["DEFAULT_SORT"])
# Parse the written articles # Parse the written articles
articles = LexiconArticle.parse_from_directory(os.path.join(lex_path, "src")) articles = LexiconArticle.parse_from_directory(os.path.join(lex_path, "src"))
# At this point, the articles haven't been cross-populated,
# so we can derive the written titles from this list
#written_titles = [article.title for article in articles]
# Once they've been populated, the articles list has the titles of all articles # Once they've been populated, the articles list has the titles of all articles
# Sort this by turn before title so prev/next links run in turn order # Sort this by turn before title so prev/next links run in turn order
articles = sorted( articles = sorted(
LexiconArticle.populate(articles), LexiconArticle.populate(articles),
key=lambda a: (a.turn, utils.titlesort(a.title))) key=lambda a: (a.turn, utils.titlesort(a.title)))
#phantom_titles = [article.title for article in articles if article.title not in written_titles]
def pathto(*els): def pathto(*els):
return os.path.join(lex_path, *els) return os.path.join(lex_path, *els)
# Write the redirect page # Write the redirect page
print("Writing redirect page...") print("Writing redirect page...")
with open(pathto("index.html"), "w", encoding="utf8") as f: with open(pathto("index.html"), "w", encoding="utf8") as f:
f.write(utils.load_resource("redirect.html").format(lexicon=config["LEXICON_TITLE"], sort=config["DEFAULT_SORT"])) f.write(utils.load_resource("redirect.html").format(
lexicon=config["LEXICON_TITLE"], sort=config["DEFAULT_SORT"]))
# Write the article pages # Write the article pages
print("Deleting old article pages...") print("Deleting old article pages...")
@ -398,38 +372,32 @@ def build_all(path_prefix, lexicon_name):
for idx in range(l): for idx in range(l):
article = articles[idx] article = articles[idx]
with open(pathto("article", article.title_filesafe + ".html"), "w", encoding="utf-8") as f: with open(pathto("article", article.title_filesafe + ".html"), "w", encoding="utf-8") as f:
content = article.build_default_content() contentblock = article.build_default_contentblock()
citeblock = article.build_default_citeblock( citeblock = article.build_default_citeblock(
None if idx == 0 else articles[idx - 1], None if idx == 0 else articles[idx - 1],
None if idx == l-1 else articles[idx + 1]) None if idx == l-1 else articles[idx + 1])
article_html = entry_skeleton.format( article_html = page.format(
title = article.title, title = article.title,
lexicon = config["LEXICON_TITLE"], content = contentblock + citeblock)
css = css,
logo = config["LOGO_FILENAME"],
prompt = config["PROMPT"],
sort = config["DEFAULT_SORT"],
content = content,
citeblock = citeblock)
f.write(article_html) f.write(article_html)
print(" Wrote " + article.title) print(" Wrote " + article.title)
# Write default pages # Write default pages
print("Writing default pages...") print("Writing default pages...")
with open(pathto("contents", "index.html"), "w", encoding="utf-8") as f: with open(pathto("contents", "index.html"), "w", encoding="utf-8") as f:
f.write(build_contents_page(articles, config)) f.write(build_contents_page(page, articles, config["INDEX_LIST"]))
print(" Wrote Contents") print(" Wrote Contents")
with open(pathto("rules", "index.html"), "w", encoding="utf-8") as f: with open(pathto("rules", "index.html"), "w", encoding="utf-8") as f:
f.write(build_rules_page(config)) f.write(build_rules_page(page))
print(" Wrote Rules") print(" Wrote Rules")
with open(pathto("formatting", "index.html"), "w", encoding="utf-8") as f: with open(pathto("formatting", "index.html"), "w", encoding="utf-8") as f:
f.write(build_formatting_page(config)) f.write(build_formatting_page(page))
print(" Wrote Formatting") print(" Wrote Formatting")
with open(pathto("session", "index.html"), "w", encoding="utf-8") as f: with open(pathto("session", "index.html"), "w", encoding="utf-8") as f:
f.write(build_session_page(config)) f.write(build_session_page(page, config["SESSION_PAGE"]))
print(" Wrote Session") print(" Wrote Session")
with open(pathto("statistics", "index.html"), "w", encoding="utf-8") as f: with open(pathto("statistics", "index.html"), "w", encoding="utf-8") as f:
f.write(build_statistics_page(articles, config)) f.write(build_statistics_page(page, articles))
print(" Wrote Statistics") print(" Wrote Statistics")
# Write auxiliary pages # Write auxiliary pages

View File

@ -1,3 +1,4 @@
<div class="contentblock">
<p>Lexipython provides support for a limited amount of Markdown-esque formatting.</p> <p>Lexipython provides support for a limited amount of Markdown-esque formatting.</p>
<pre style="background:#eeeeee"> <pre style="background:#eeeeee">
# Player: PN # Player: PN
@ -7,17 +8,50 @@
This is an example page. This is an example page.
Some words are //italicized//, Some words are //italicized//,
and some words are **bolded**. and some words are **bolded**.
All of these sentences are part of the same paragraph. All of these sentences are part of the same
paragraph.
This is a new paragraph.\\ This is a new paragraph.\\
Unlike the last paragraph, this line will be after a line break within the paragraph. Unlike the last paragraph, this line will be after a
line break within the paragraph.
This is an [[example citation|Phantom page]]. You can also cite a [[phantom page]] with just the title. This is an [[example citation|Phantom page]]. You can
also cite a [[phantom page]] with just the title.
~Dr. X. Amplepage ~Dr. X. Amplepage
</pre> </pre>
<p>Each turn, fill out the header with your player information, the current turn, and the title of your entry. The <i>Player</i> field can be anything as long as it's the same for all articles you write (even when they're by different characters). Using your initials is recommended.</p> <p>Each turn, fill out the header with your player information, the current
<p>Two line breaks begins a new paragraph. A single line break does nothing, unless the line is ended by a double backslash (\\).</p> turn, and the title of your entry. The <i>Player</i> field can be anything
<p>Text bounded by ** will be bolded: **bold** produces <b>bold</b>. Text bounded by // will be italicized: //italics// produces <i>italics</i>.</p> as long as it's the same for all articles you write (even when they're by
<p>To cite another Lexicon entry, use double brackets. Text in double brackets will cite and link to the entry of the same name: [[Example page]] produces <a href="Example_page.html" class="phantom">Example page</a>. Text in double brackets split with a | will alias the link as the left text and link to the entry with the name of the right text: [[this text|Example page]] produces <a href="Example_page.html" class="phantom">this text</a>. <b>You must be precise in the entry title you cite to.</b> Citations to "Example" vs. "The Example" will point to different entries and create different phantoms, and your GM will probably have to clean up after you.</p> different characters). Using your initials is recommended.</p>
<p>Beginning a paragraph with ~ will right-align it and place a horizontal line above it. Use this for signing your entry with your scholar's name.</p> <p>Two line breaks begins a new paragraph. A single line break does nothing,
unless the line is ended by a double backslash (\\).</p>
<p>Text bounded by ** will be bolded: **bold** produces <b>bold</b>. Text
bounded by // will be italicized: //italics// produces <i>italics</i>.</p>
<p>To cite another Lexicon entry, use double brackets. Text in double brackets
will cite and link to the entry of the same name: [[Example page]] produces
<a href="Example_page.html" class="phantom">Example page</a>. Text in
double brackets split with a | will alias the link as the left text and
link to the entry with the name of the right text: [[this text|Example page]]
produces <a href="Example_page.html" class="phantom">this text</a>. <b>You
must be precise in the entry title you cite to.</b> Citations to
"Example" vs. "The Example" will point to different entries and create
different phantoms, and your GM will probably have to clean up after
you.</p>
<p>Beginning a paragraph with ~ will right-align it and place a horizontal line
above it. Use this for signing your entry with your scholar's name.</p>
</div>
<div class="contentblock">
<h1>Example page</h1>
<p>This is an example page.
Some words are <i>italicized</i>,
and some words are <b>bolded</b>.
All of these sentences are part of the same
paragraph.</p>
<p>This is a new paragraph.<br>
Unlike the last paragraph, this line will be after a
line break within the paragraph.</p>
<p>This is an <a href="Phantom_page.html" class="phantom">example citation</a>. You can
also cite a <a href="Phantom_page.html" class="phantom">phantom page</a> with just the title.</p>
<hr><span class="signature"><p>Dr. X. Amplepage</p></span>
</div>

View File

@ -1,18 +1,67 @@
<div class="contentblock">
<ol> <ol>
<li>At the beginning of the game, you will be provided with a <i>topic statement</i> that sets the tone for the game. Use it for inspiration and a stepping-stone into shaping the world of the Lexicon.</li> <li>Each Lexicon has a <i>topic statement</i> that sets the tone for the game.
<li>Each round, you will be assigned an <i>index</i>, a grouping of letters. Your entry must alphabetize under that index.<ol> It provides a starting point for shaping the developing world of the
<li>Each index has a number of open slots equal to the number of players, which are taken up by article titles when an article is written in that index or a citation is made to an unwritten article, or <i>phantom</i>. If there are no open slots in your index, you must write the article for a phantom in that index.</li> Lexicon. As it is a starting point, don't feel contrained to write only
<li>"The" and "A" aren't counted in indexing.</li></ol></li> about the topics mentioned directly in it.</li>
<li>Once you've picked an article title, write your article on that subject.<ol> <li>Articles are sorted under an <i>index</i>, a grouping of letters. An article is
<li>There are no hard and fast rules about style. Try to sound like an encyclopedia entry or the overview section at the top of a wiki article.</li> in an index if its first letter is in that group of letters. "The", "A",
<li>You must respect and not contradict any factual content of any posted articles. You may introduce new facts that place things in a new light, provide alternative interpretations, or flesh out unexplained details in unexpected ways; but you must not <i>contradict</i> what has been previously established as fact.</li> and "An" aren't counted in indexing. <i>Example: One of the indices is JKL.
<li>Aim for around 200-300 words. Going over is okay, but be reasonable.</li></ol></li> An article titled 'The Jabberwock' would index under JKL, not T's index.</i></li><ol>
<li>Your article must cite other articles in the Lexicon. Sometimes these citations will be to phantoms, articles that have not been written yet.<ol> <li>Until the game is over, some of the articles will have been cited, but not
<li>On the first turn, your article must cite <i>exactly two</i> phantom articles.</li> yet written. These are called <i>phantom</i> articles. A phantom article has a
<li>On subsequent turns, your article must cite <i>exactly two</i> phantom articles, either already-cited phantoms or new ones. Your article must also cite <i>at least one</i> written article.</li> title, which is defined by the first citation to it, but no content.</li>
<li>On the penultimate turn, you must cite <i>exactly one</i> phantom article and <i>at least two</i> written articles.</li> <li>Generally, an index has a number of "slots" equal to the number of players.
<li>On the final turn, you must cite <i>at least three</i> written articles.</li> When an article is first written or cited, it takes up one slot in its
<li>You may not cite an entry you wrote. You may cite phantoms you have cited before.</li> corresponding index.</li></ol>
<li>Once you cite a phantom, you cannot choose to write it if you write an article for that index later.</li></ol></li> <li>Each turn, you will be assigned to write in an index.</li><ol>
<li>Your articles should be written from the perspective of your character.
<p><b>Ersatz Scrivener.</b> In the course of the game, it may come to pass that a scholar is assigned an index in which no slots are available to them, because they have cited all the available phantoms in their previous articles. When this happens, the player instead writes their article as Ersatz Scrivener, radical skeptic. Ersatz does not believe in the existence of whatever he is writing about, no matter how obvious it seems to others or how central it is in the developing history of the world. All references, testimony, etc. with regard to its existence are tragic delusion at best or malicious lies at worst. Unlike the other scholars, Ersatz does not treat the research of his peers as fact, because he does not believe he has peers. Players writing articles as Ersatz are encouraged to name and shame the work of the misguided amateurs collaborating with him.</p> Your character should be a scholar collaborating with the other
scholars on the production of the Lexicon. You should play the same
character for the duration of the game.</li>
<li>If the index has open slots, you may come up with a new article title
and write an article under that title. If all unwritten slots in your
index are filled by phantom articles, you must choose one of them and
write it.</li>
<li>There are no hard and fast rules about style, but it is recommended
that players imitate an encyclopedic style to stay true to the game's
conceit.</li>
<li>There are no hard and fast rules about length, but it is recommended
that the Editor enforce a maximum word limit. In general, aiming for
200-300 words is ideal.</li>
<li>You must respect and not contradict the factual content of all written
articles. You may introduce new facts that put things in a new light,
provide alternative interpretations, or flesh out unexplained details
in unexpected ways; but you must not <i>contradict</i> what has been
previously established as fact. Use the "yes, and" rule from improv
acting: accept what your fellow scholars have written and add to it in
new ways, rather than trying to undo their work. This rule includes
facts that have been established in written articles about the topics
of phantom articles.</li></ol>
<li>Each article will cite other articles in the Lexicon.</li><ol>
<li>You may not cite an entry that you have written. When you write an
article, you may not cite it in later articles.</li>
<li>As a corollary, you may not write phantom articles that you have cited.
If you cite an article and then write it later, your former article
now cites you, which is forbidden per the above.</li>
<li>On the first turn, there are no written articles. Your first article
must cite <i>exactly two</i> phantom articles.</li>
<li>On subsequent turns, your article must cite <i>exactly two</i> phantoms,
but you can cite phantoms that already exist. Your article must also
cite <i>at least one</i> written article. You can cite more than one.</li>
<li>On the penultimate turn, you must cite <i>exactly one</i> phantom
article and <i>at least two</i> written articles.</li>
<li>On the final turn, you must cite <i>at least three</i> written articles.</li></ol>
<li>As the game goes on, it may come to pass that a player must write an
article in an index, but that index is full, and that player has already
cited all the phantoms in it. When this happens, the player instead writes
their article as **Ersatz Scrivener**, radical skeptic. Ersatz does not
believe in the existence of whatever he is writing about, no matter how
obvious it seems to others or how central it is in the developing history
of the world. For Ersatz, all references, testimony, etc. with regard to
its existence are tragic delusion at best or malicious lies at worst.
Unlike the other scholars, Ersatz does not treat the research of his peers
as fact, because he does not believe he has peers. Players writing articles
as Ersatz are encouraged to lambast the amateur work of his misguided
"collaborators".</li>
</div>