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))