Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial pass at rst2html parser.

  • Loading branch information...
commit 89ae4a47f0e7b3c40143569fb0f23c4abbcb4722 1 parent d2f0d84
@cgay cgay authored
View
37 README.rst
@@ -183,3 +183,40 @@ Backlinks (Page References)
Use for: users to see what points to a page
Update page = update backlink file for all pages it references or dereferences.
+
+
+Markup Language
+===============
+
+The markup language is an augmented version of `ReStructured Text
+(RST) <http://docutils.sourceforge.net/rst.html>`. An initial pass is
+made over the markup source to resolve wiki-specific markup and then
+the resulting text is passed directly to rst2html.
+
+All wiki directives start with ``{{`` and ends with ``}}``. Because
+page links are expected to be the most common by far, they have an
+optional shortened syntax::
+
+ {{page: Foo, text: Bar}} -- link text "Bar" to page "Foo"
+ {{Foo,Bar}} -- shorthand for {{page:Foo,text:Bar}}
+ {{Foo}} -- shorthand for {{page:Foo,text:Foo}}
+ {{page: "x,y"}} -- names may be quoted
+ {{page: 'The "x" Page'}} -- single or double quotes work.
+ {{user: jdoe, text: Jon}} -- a user link
+ {{group: group}} -- a group link
+ {{wiki: off}} -- turn off wiki markup parsing
+ {{wiki: on}} -- turn it back on
+ {{escape: "[[" "]]"}} -- use [[ and ]] instead of {{ and }}
+
+The wiki pre-parser knows nothing about RST parsing. It simply
+searches the raw markup for ``{{`` and assumes that's a wiki
+directive. If you need to put a literal ``{{`` or ``}}`` in the
+generated output it can be done like this::
+
+ {{wiki:off}}{{{{wiki:on}}
+
+or by changing the escape character sequences::
+
+ {{escape: "[[" "]]"}}
+ Now {{ and }} are just normal text and [[Foo]] is a page link.
+ [[escape: "{{" "}}"]]
View
2  config.xml
@@ -42,6 +42,8 @@
git-repository-root="c:/tmp/wiki/main-storage"
git-user-repository-root="c:/tmp/wiki/user-storage"
git-executable="c:/Program Files/Git/bin/git"
+ python-executable="c:/python27/python.exe"
+ rst2html="c:/docutils/tools/rst2html.py"
>
<!-- Note that the administrator's email address will be the one
from which account emails are sent, so it runs a high spam risk.
View
2  dylan/library.dylan
@@ -84,7 +84,7 @@ define module %wiki
use smtp-client;
use streams;
use strings,
- import: { trim };
+ import: { equal?, trim };
use substring-search;
use table-extensions,
rename: { table => make-table };
View
9 dylan/main.dylan
@@ -80,6 +80,15 @@ define sideways method process-config-element
error("A <mail> element must be specified in the config file.");
end;
+ *python-executable* := get-attr(node, #"python-executable")
+ | error("The 'python-executable' attribute must be specified in the 'wiki' "
+ "config file element.");
+ *rst2html* := get-attr(node, #"rst2html")
+ | error("The 'rst2html' attribute must be specified in the 'wiki' "
+ "config file element.");
+ *rst2html-template* := get-attr(node, #"rst2html-template")
+ | error("The 'rst2html-template' attribute must be specified in the 'wiki' "
+ "config file element.");
end method process-config-element;
define method process-administrator-configuration
View
36 dylan/page.dylan
@@ -79,6 +79,11 @@ define method find-page
element(*pages*, title, default: #f)
end;
+define method page-exists?
+ (title :: <string>) => (exists? :: <boolean>)
+ find-page(title) & #t
+end;
+
// The latest revisions of all pages are loaded at startup for now (to
// simplify searches and iteration over lists of pages) so this will only
// load anything if the 'revision' arg is supplied. Note that 'revision'
@@ -451,6 +456,13 @@ define method respond-to-get
end;
end method respond-to-get;
+define tag show-page-content in wiki
+ (page :: <wiki-dsp>)
+ ()
+ let xhtml = wiki-markup-to-html(*page*.page-content, *page*.page-title);
+ output("%s", xhtml);
+end;
+
//// Edit Page
@@ -533,6 +545,15 @@ define method respond-to-post
end;
end method respond-to-post;
+define tag show-page-preview in wiki
+ (page :: <edit-page-page>)
+ ()
+ let markup = get-query-value("content");
+ let title = get-query-value("title");
+ output("%s", wiki-markup-to-html(markup, title));
+end;
+
+
//// View Diff
@@ -651,21 +672,6 @@ define tag show-page-owner in wiki
end;
end;
-define tag show-page-content in wiki
- (page :: <wiki-dsp>)
- (content-format :: false-or(<string>))
- let raw-content = get-attribute(page-context(), "content")
- | (*page* & *page*.page-content)
- | get-query-value("content")
- | "";
- case
- content-format = "xhtml"
- => output("%s", wiki-markup-to-html(raw-content)); // parse-wiki-markup(content);
- otherwise
- => output("%s", raw-content);
- end case;
-end;
-
define tag show-version in wiki
(page :: <wiki-dsp>)
()
View
106 dylan/rst-parser.dylan
@@ -0,0 +1,106 @@
+Module: %wiki
+Synopsis: Parser for augmented RST markup
+Author: Carl Gay
+
+// See README.txt for a description of the markup language we parse here.
+
+define variable *python-executable* :: <string> = "python";
+define variable *rst2html* :: <string> = "rst2html.py";
+define variable *rst2html-template* :: <string> = "rst2html-template.txt";
+
+define variable *markup-prefix* :: <string> = "{{";
+define variable *markup-suffix* :: <string> = "}}";
+
+
+/// External entry point to the parser.
+///
+define method wiki-markup-to-html
+ (markup :: <string>, title :: <string>,
+ #key start :: <integer> = 0)
+ => (html :: <string>)
+ let chunks :: <sequence> = parse-wiki-markup(markup, title);
+ rst2html(chunks)
+end method wiki-markup-to-html;
+
+define function parse-wiki-markup
+ (markup :: <string>, title :: <string>)
+ => (rst-chunks :: <sequence>)
+ let chunks :: <sequence> = make(<stretchy-vector>);
+ iterate loop (start :: <integer> = 0)
+ if (start < markup.size)
+ let markup-bpos = subsequence-position(markup, *markup-prefix*, start: start);
+ if (~markup-bpos)
+ add!(chunks, slice(markup, start, #f));
+ else
+ add!(chunks, slice(markup, start, markup-bpos));
+ let in-bpos = markup-bpos + *markup-prefix*.size;
+ let markup-epos = iterate loop (start = in-bpos)
+ case
+ start >= markup.size =>
+ #f;
+ equal?(markup, *markup-suffix*, start1: start) =>
+ start;
+ otherwise =>
+ loop(start + 1);
+ end;
+ end;
+ if (markup-epos)
+ // For now only handle {{Page Name}}
+ let title = trim(slice(markup, in-bpos, markup-epos));
+ add!(chunks, make-page-anchor(title, title));
+ loop(markup-epos + *markup-suffix*.size);
+ else
+ error("Wiki markup close tag (%=) not found at index %d in page %s",
+ *markup-suffix*, markup-bpos, title);
+ end;
+ end if;
+ end if;
+ end iterate;
+ chunks
+end function parse-wiki-markup;
+
+define function rst2html
+ (rst-chunks :: <sequence>) => (html :: <string>)
+ let command = format-to-string("%s %s --template %s",
+ *python-executable*, *rst2html*, *rst2html-template*);
+ let error = #f;
+ let html = "";
+ let process = #f;
+ block ()
+ log-debug("running rst2html");
+ let (exit-code, signal, child, stdin, stdout, stderr)
+ = run-application(command,
+ asynchronous?: #t,
+ input: #"stream", output: #"stream", error: #"stream");
+ log-debug("ran rst2html");
+ process := child;
+ for (chunk in rst-chunks)
+ write(stdin, chunk);
+ end;
+ force-output(stdin);
+ close(stdin);
+ log-debug("wrote markup chunks");
+ html := read-to-end(stdout);
+ log-debug("read stdout %d bytes", html.size);
+ error := read-to-end(stderr);
+ log-debug("read stderr %d bytes", error.size);
+ cleanup
+ // prevent zombies
+ process & wait-for-application-process(process);
+ end;
+ if (~empty?(error))
+ log-error("stderr: %s", error);
+ end;
+ html
+end function rst2html;
+
+
+define function make-page-anchor
+ (title :: <string>, text :: <string>) => (html-anchor :: <string>)
+ if (page-exists?(title))
+ format-to-string("<a href=\"/page/view/%s\">%s</a>", title, text)
+ else
+ format-to-string("%s <a href=\"/page/view/%s\">[?]</a>", text, title)
+ end
+end;
+
View
7 dylan/wiki.lid
@@ -5,11 +5,12 @@ Files: library
user
group
access
- parser
+ rst-parser
page
feed
git-storage
main
Other-files: ../README.rst
- ../koala-config.xml
- ../TODO
+ ../koala-config.xml
+ ../TODO
+ ../rst2html-template.txt
View
8 rst2html-template.txt
@@ -1,8 +1,4 @@
-%(head_prefix)s
-%(head)s
+<div class="document">
%(stylesheet)s
-%(body_prefix)s
-%(body_pre_docinfo)s
-%(docinfo)s
%(body)s
-%(body_suffix)s
+</div>
View
10 www/dsp/edit-page.dsp
@@ -23,7 +23,15 @@
<p><font color="red">THIS IS A PREVIEW. DON'T FORGET TO SAVE THE PAGE.</font></p>
<hr/>
<div class="preview">
- <%dsp:include url="view-page-content.dsp"/>
+ <dsp:if test="can-view-content?">
+ <dsp:then>
+ <wiki:show-page-preview/>
+ <%dsp:include url="view-page-tags.dsp"/>
+ </dsp:then>
+ <dsp:else>
+ You do not have permission to view this page.
+ </dsp:else>
+ </dsp:if>
</div>
<hr/>
</dsp:when>
View
2  www/dsp/main.dsp
@@ -47,7 +47,7 @@
<wiki:list-pages tags="news">
<h3 class="news summary"><a href="<wiki:base/>/page/view/<wiki:show-page-title/>"><wiki:show-page-title/></a></h3>
<small class="date"><wiki:show-page-published formatted="%d. %B %Y %H:%M"/></small>
- <wiki:show-page-content format="markup"/>
+ <wiki:show-page-xhtml/>
</wiki:list-pages>
</div>
View
17 www/dsp/view-page-content.dsp
@@ -1,17 +0,0 @@
-<%dsp:taglib name="wiki"/>
-
- <dsp:if test="can-view-content?">
- <dsp:then>
- <wiki:show-page-content content-format="xhtml"/>
- <dsp:loop over="page-tags" var="tag" header="<hl/><h3>Tags:</h3>">
- <dsp:get name="tag"/>
- <a href="<wiki:base/>/feed/tags/<dsp:get name='tag'/>">
- <img border="0" src="<wiki:base/>/static/images/feed-icon-14x14.png" alt="Atom feed for this tag"/>
- </a>
- <dsp:unless test="loop-end?">, </dsp:unless>
- </dsp:loop>
- </dsp:then>
- <dsp:else>
- You do not have permission to view this page.
- </dsp:else>
- </dsp:if>
View
7 www/dsp/view-page-tags.dsp
@@ -0,0 +1,7 @@
+ <dsp:loop over="page-tags" var="tag" header="<hl/><h3>Tags:</h3>">
+ <dsp:get name="tag"/>
+ <a href="<wiki:base/>/feed/tags/<dsp:get name='tag'/>">
+ <img border="0" src="<wiki:base/>/static/images/feed-icon-14x14.png" alt="Atom feed for this tag"/>
+ </a>
+ <dsp:unless test="loop-end?">, </dsp:unless>
+ </dsp:loop>
View
10 www/dsp/view-page.dsp
@@ -34,7 +34,15 @@
<dsp:show-page-errors/>
<dsp:show-page-notes/>
- <%dsp:include url="view-page-content.dsp"/>
+ <dsp:if test="can-view-content?">
+ <dsp:then>
+ <wiki:show-page-content/>
+ <%dsp:include url="view-page-tags.dsp"/>
+ </dsp:then>
+ <dsp:else>
+ You do not have permission to view this page.
+ </dsp:else>
+ </dsp:if>
</div>
</div>
Please sign in to comment.
Something went wrong with that request. Please try again.