Pmwiki /
Replace
Wiki Replacement
Problems with Pmwiki
- Pmwiki metadata is stored along with content in pmwiki's files. This makes it very difficult to parse.
- Pmwiki is no longer actively maintained
- Pmwiki depends upon PHP which we lack a developer community for
- Pmwiki's markup is not very popular or familiar to new users
- Pmwiki is limited to web only, but we will need to offer access to multiple protocols like gopher, email, and telnet to avoid censorship
Strict Requirements
- Support basic functionality for older web browsers like w3m, lynx, netsurf, dillo, mothra. Users must be able to at least read wiki pages, and preferably write/administrate. These browsers have limited javascript support, or none at all.
- Avoid unreasonable privacy or censorship concerns. Google Go should be avoided because of the potential for always-on telemetry, and because Google has the ability to ban entire countries like Iran and Russia.
- Do not require the use of any SQL or noSQL databases. Keep it optional.
- Revision control should be handled by a separate utility rather than by the wiki itself. (For example, use got or CVS for versioning)
- The code should be simple enough so our teammates can regularly maintain and contribute to it.
- User-written content should be stored in plain text files in a simple markup language.
- It must be possible for users to be able to read and write articles outside of the web
- It must be possible for users to be able to administrate the wiki from outside of the web
- Follow the principles of progressive enhancement. Core functionality should be present for users with limited clients, and extra functionality can be available for users with more featureful clients.
- Web contributors must be allowed to provide extra web functionality.
Preferences
- For languages, perl, C, korn shell, and lisp are preferred because that is what our network will actively teach
- Using got for revision control is preferred because it is an openbsd project and avoids the complexity of git
- Prefer John Gruber's markdown (https://daringfireball.net/projects/markdown/) because it is simple and well known by many users
Possible Solution:
- Consider switching the web wiki to ikiwiki or something similar. Ikiwiki uses a proper revision control system (could be git or got). It is written in perl, which our network will have developers for
- A pmwiki markup to markdown translator will be needed to obtain the markdownfiles for the new wiki.
Proposed Markdown:
- start with what ikiwiki already has for the base: https://ikiwiki.info/ikiwiki/
- I have created a possible parser that takes pmwiki files and converts to markdown.
- pmWiki Cookbook to produce markdown output https://www.pmwiki.org/wiki/Cookbook/MarkdownOutput
- pmwiki2markdown parser
import sys, re, os
def read_file(filename):
data = {}
with open(filename, 'r') as f:
for line in f:
line = line.strip()
if '=' in line:
# ignores the diff values
if ':' in line and '=' in line and line.index(':') < line.index('='):
break
else:
key, value = line.split('=', 1)
data[key] = value
elif line == '':
break
return data
def create_markdown(filename):
print(f"--- {filename} ---")
# Read the data from the file
data=read_file(filename)
title = ""
text = ""
# Extract the relevant information
#if 'title' in data.keys():
# title=data['title']
if 'text' in data.keys():
text=data['text']
# Perform pmwiki-to-markdown replacements
text = text.replace("%0a","\n")
markdown_text = (
text.replace("\n\n", "\n")
.replace("\n", "\n\n")
.replace("'''", "**")
.replace("''", "_")
.replace("[@","##STARTCODEBLOCK##\n")
.replace("@]","##ENDCODEBLOCK##\n")
.replace("!!! ","### ")
.replace("!! ","## ")
.replace("! ","# ")
.replace("@@","`")
)
# Replace the title text with a # heading
markdown_text = re.sub(r'^\(:title (.*?)\:\)$', r'# \1', markdown_text, flags=re.MULTILINE)
markdown_text = markdown_text.split("\n")
codeblock=0
index_to_be_removed = []
for index,value in enumerate(markdown_text):
if(value =="##STARTCODEBLOCK##"):
index_to_be_removed.append(index)
codeblock=1
elif(value =="##ENDCODEBLOCK##"):
index_to_be_removed.append(index)
codeblock=0
else:
if(codeblock==1):
markdown_text[index] = " "+value
# Reversing Indices List
indicesList = sorted(index_to_be_removed, reverse=True)
# Traversing in the indices list
for indx in indicesList:
# checking whether the corresponding iterator index is less than the list length
if indx < len(markdown_text):
# removing element by index using pop() function
markdown_text.pop(indx)
markdown_text = "\n".join(markdown_text)
#change the wikilinks to ikiwiki format
# Instead of [[link|text to display]] make it [text to display||link]
markdown_text = re.sub(r'\[\[(.*?)\|(.*?)\]\]', r'[[\2|\1]]', markdown_text)
return markdown_text
name = sys.argv[1]
if(len(name.split("."))>1):
folder_name,file_name = name.split(".")
if(not os.path.exists(os.path.join("output",folder_name.lower()))):
os.makedirs(os.path.join("output",folder_name.lower()))
with open(os.path.join("output",folder_name.lower(),f"{file_name.lower()}.mdwn"),'w+') as output:
output.write(create_markdown(name))
else:
with open(os.path.join("output",f"{name}.mdwn"),'w+') as output:
output.write(create_markdown(name))
