“pmarkup” (uncapitalized), meaning “paragraph markup”, is a system I’ve created for my own wiki-like syntax.

My design goals included:

  • extremely easy to write a parser for (see also: SimpleSystems)
  • extremely easy to extend for a particular purpose (see also: ExpertiseBuilding)
  • able to render most things you’d want to see on the web
  • assist with common operations, like italicizing and bolding

Basics of the format

Essentially, it makes the structure of the page explicit.

I might have some details wrong, it’s been a while since I worked with it, but here’s the basic idea:

  This is a paragraph!

  This is another paragraph.
  All of this text is within that paragraph.
  So, even this text, over here.

There are two fundamental columns --

  • col 0 – the command column
  • col 2 – the content column

Anything put into the command column, commands a state change in rendering, basically.

Anything put into the content column, accumulates.

Here’s an example including an image:

  Here's a picture:


  That was the CommunityWiki Logo.

Headings like so:

h3 a section

  Here's a paragraph in there.
  Note that's an <h3> heading up above.

  Yet another paragraph, ...

p #foo
  This paragraph can be accessed by anchor point "foo".

You can also inject raw HTML:

  <div class="foo">

Current Status

I wrote this 6 years ago, and kind of left it to the side, and didn’t return to it.

It’s broken in some important ways. I think it’s fixable and worthy, but it’ll take time.

If I recall right, it doesn’t handle multiple instances of italicizing and bolding and linking and such correctly, within a paragraph, but I’d need to reinvestigate it to remember what’s broken, and to think about how to fix it.


The principal “wart,” I think, is something like: “How do you cheaply and easily write a system that bolds, italicizes, and links, in a way that is simply expressed, and does most everything we want it to do?”

Everything we want it to do:

  • italicize
  • bold
  • links
  • combining – for example, italics+bold, italics+link, bold+link
  • multiple instances of italicization, bolding, and linking, within a single line
  • extensible (for example, if you want underlining, if you want strikethrough, it should be easy to add, and it should combine)

Python Code

# 2014-05-21

import sys, re

p = False     # within <p>?
code = False  # within <p><code><pre>?
ul = False    # within <ul>...</ul> ?
html = False  # within raw HTML?

table = False # within <table> ?
row = False   # within <row> ?
cell = False  # within <cell> ?
headers = False # in a headers row?

i = 0  # What's the minimum indentation for new text?
x = 0  # What's the current x-position?

fullline = None  # the full line (current)
word = None      #   word currently being chewed (⇒)
line = None      #   remainder of full line; being chewed up (⇒)

L = []  # output

D = {"FILENAME": "output.html",
     "TEMPLATE": None}  # stored values

f = open("../05_wiki2014/pages/"+sys.argv[1], "rb")

def chew():
    global word, line
    ret = line.split(None, 1)
    word = ret[0] if len(ret) > 0 else None
    line = ret[1] if len(ret) == 2 else ""
    return len(ret)

def out(pre, text, post=0):
    global i, x
    i += pre
    if x < i: L.append(" "*(i-x)); x = i
    L.append(text); x += len(text)
    i += post

def nl(): global x; L.append("\n"); x = 0

def closep():
    global p
    if p: out(-3, "</p>", 0); nl(); nl(); p = False

def closecode():
    global code
    if code: out(0, "</pre></code></p>", 0); nl(); code = False

def closelist():
    global ul
    if ul: out(-4, "</ul>", 0); nl(); nl(); ul = False

def closehtml(): global html; html = False

def closetop(): closep(); closecode(); closelist(); closehtml()

def closecell():
    global cell
    if cell:
        out(-4, "</th>" if headers else "</td>", 0); nl()
        cell = False

def closerow():
    global row
    if row: out(-2, "</tr>", 0); nl(); row = False

def closetable():
    global table
    if table: out(-2, "</table>", 0); nl(); nl(); table = False

html_escape_table = {
    "&": "&amp;",
    '"': "&quot;",
    "'": "&apos;",
    ">": "&gt;",
    "<": "&lt;",

def esc(s): return "".join(html_escape_table.get(c,c) for c in s)

def text(s):
    s = esc(s)
    s = re.sub('[*](.+?)[*]', '<b>\\1</b>', s)
    s = re.sub('[_](.+?)[_]', '<i>\\1</i>', s)
    s = re.sub('[{](.+?)[}]', '<code>\\1</code>', s)
    s = re.sub('xxx(.+?)xxx', '<del>\\1</del>', s)
    s = re.sub('\[(.+?)\][(](.+?)[)]', '<a href="\\1">\\2</a>', s)
    return s.replace("--", "—")

for fullline in f.readlines():
    fullline = fullline.decode("utf-8")
    line = fullline.rstrip()
    if line.strip() == "": continue
    if chew() == 0: continue
    if fullline[0] != " ":
        if word == "p":
            out(0, "<p>", 3)
            if line.startswith("#"):
                out(0, """<a name="{}"></a>""".format(word[1:]), 0)
            p = True
        elif word == "code":
            out(0, "<p><code><pre>", 0); nl(); code = True
        elif word == "//": pass
        elif word.endswith(":"): D[word[:-1].upper()] = line
        elif word in "h1 h2 h3 h4 h5 h6":
            out(0, "<{}>{}</{}>".format(word, text(line), word), 0); nl(); nl()
        elif word == "li":
            if not ul: closetop(); out(0, "<ul>", 4); nl(); ul = True
            out(0, "<li>{}</li>".format(text(line)), 0); nl()
        elif word in ["img", "img-r", "img-l"]:
            aligntext = {"img-r": ' align="right"',
                         "img-l": ' align="left"'}.get(word, "")
            alttext = ' alt="{}"'.format(line) if chew() else ''
            out(0, '<img src="{}"'.format(word) + alttext + aligntext + '>', 0); nl()
        elif word in ["headers", "row"]:
            if not table:
                out(0, "<table>", 2); nl()
                table = True; row = False; cell = False
            out(0, "<tr>", 2); nl()
            row = True
            headers = (word == "headers")
        elif word == "cell":
            if not table:
                out(0, "<table>", 2); nl()
                out(0, "<tr>", 2); nl()
                table = True; row = True
            if not row:
                out(0, "<tr>", 2); nl(); row = True
            out(0, "<th>" if headers else "<td>", 4); cell = True
            if line:
                out(0, text(line)+("</th>" if headers else "</td>"), -4)
                cell = False
        elif word == "...": closetable(); closetop()
        elif word == "html": closetop(); html = True
    elif len(fullline.rstrip()) >= 2:
        if html: out(0, fullline[2:], 0)
        else: out(0,text(fullline.rstrip()[2:]),0)


f = open(D["FILENAME"], "wb")

    text = open("../05_wiki2014/templates/"+D["TEMPLATE"]+".html", "r").read()
    text = text.replace("{{TITLE}}", D.get("TITLE", "TITLE"))
    text = text.replace("{{BODY}}", "".join(L))


See Also