Podpora Markdown syntaxe
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 06 Nov 2011 00:08:05 +0100
changeset 1164ddc1020a154
parent 115 e5bfc969d41f
child 117 79ce65d63cce
Podpora Markdown syntaxe
na začátek odesílané zprávy stačí přidat:
#!markdown
a zpráva se pak prožene Markdown procesorem (spouštěno přes sudo pod jiným uživatelem)
a pak teprve přes standardní XSL transformaci.

1) Vytvořit uživatele a skupinu markdown

2) Do /etc/sudoers přidat:
Cmnd_Alias MARKDOWN = /usr/bin/markdown
%markdown ALL = (%markdown) NOPASSWD : MARKDOWN

3) Uivatele, pod kterým běží NNTP démon, přidat do skupiny markdown
helpers/mimeXhtmlPart.xsl
src/org/sonews/storage/DrupalMessage.java
     1.1 --- a/helpers/mimeXhtmlPart.xsl	Sat Nov 05 00:06:09 2011 +0100
     1.2 +++ b/helpers/mimeXhtmlPart.xsl	Sun Nov 06 00:08:05 2011 +0100
     1.3 @@ -130,6 +130,7 @@
     1.4  		</blockquote>
     1.5  	</xsl:template>
     1.6  	
     1.7 +	
     1.8  	<!-- Tučné písmo -->
     1.9  	<xsl:template match="h:b">
    1.10  		<strong>
    1.11 @@ -137,6 +138,7 @@
    1.12  		</strong>
    1.13  	</xsl:template>
    1.14  	
    1.15 +	
    1.16  	<!-- Skloněné písmo -->
    1.17  	<xsl:template match="h:i">
    1.18  		<em>
    1.19 @@ -145,6 +147,12 @@
    1.20  	</xsl:template>
    1.21  	
    1.22  	
    1.23 +	<!-- Markdown dává do pre ještě code – to ale nepotřebujeme, stačí nám pre a v něm rovnou text -->
    1.24 +	<xsl:template match="h:pre[h:code]">
    1.25 +		<pre><xsl:apply-templates select="h:code/node()"/></pre>
    1.26 +	</xsl:template>
    1.27 +	
    1.28 +	
    1.29  	<!--
    1.30  		Další povolené značky (jejich případné atributy zahodíme).
    1.31  		Ostatní elementy odfiltrujeme (zbude z nich jen text). 
     2.1 --- a/src/org/sonews/storage/DrupalMessage.java	Sat Nov 05 00:06:09 2011 +0100
     2.2 +++ b/src/org/sonews/storage/DrupalMessage.java	Sun Nov 06 00:08:05 2011 +0100
     2.3 @@ -71,6 +71,11 @@
     2.4   */
     2.5  public class DrupalMessage extends MimeMessage {
     2.6  
     2.7 +	/**
     2.8 +	 * If body of message posted by user through NNTP starts with this text,
     2.9 +	 * it will be treated as formated text in Markdown syntax.
    2.10 +	 */
    2.11 +	private static final String MARKDOWN_HEADER = "#!markdown\r\n";
    2.12  	private static final Logger log = Logger.getLogger(DrupalMessage.class.getName());
    2.13  	private static final String MESSAGE_ID_HEADER = "Message-ID";
    2.14  	private static final String CRLF = "\r\n";
    2.15 @@ -266,6 +271,33 @@
    2.16  	}
    2.17  
    2.18  	/**
    2.19 +	 * Converts markdown to XHTML.
    2.20 +	 * @param markdown text in Markdown syntax
    2.21 +	 * @return XHTML document (with html/body elements)
    2.22 +	 * @throws StorageBackendException when markdown proces returned any errors 
    2.23 +	 * (other exceptions are thrown when afterwards XHTML validation fails).
    2.24 +	 */
    2.25 +	private String readXhtmlTextMarkdown(String markdown) throws TransformerException, IOException, ParserConfigurationException, SAXException, StorageBackendException {
    2.26 +		Runtime r = Runtime.getRuntime();
    2.27 +		Process p = r.exec(new String[]{"sudo", "-u", "markdown", "/usr/bin/markdown"});
    2.28 +
    2.29 +		PrintStream processInput = new PrintStream(p.getOutputStream());
    2.30 +		processInput.print(markdown);
    2.31 +		processInput.close();
    2.32 +
    2.33 +		String errors = streamToString(p.getErrorStream());
    2.34 +		String htmlFragment = streamToString(p.getInputStream());
    2.35 +
    2.36 +		if (errors.length() == 0) {
    2.37 +			String htmlDocument = makeSimpleXHTML(htmlFragment);
    2.38 +			String xhtmlDocument = readXhtmlText(htmlDocument, null, -1, null, null, null);
    2.39 +			return xhtmlDocument;
    2.40 +		} else {
    2.41 +			throw new StorageBackendException("Error while transforming Markdown to XHTML: " + errors);
    2.42 +		}
    2.43 +	}
    2.44 +
    2.45 +	/**
    2.46  	 * Does not parse XML works just with text.
    2.47  	 * @param body XHTML fragment that should be put between &lt;body&gt; and &lt;/body&gt;
    2.48  	 * @return simple XHTML document (body wrapped in html and body tags)
    2.49 @@ -503,13 +535,21 @@
    2.50  		try {
    2.51  			Object c = getContent();
    2.52  			if (isMimeType("text/plain") && c instanceof String) {
    2.53 -				String xhtml = readXhtmlText(
    2.54 -						(String) c,
    2.55 -						getSubject(),
    2.56 -						getParentID(),
    2.57 -						null,
    2.58 -						null,
    2.59 -						null);
    2.60 +				String inputText = (String) c;
    2.61 +				String xhtml;
    2.62 +
    2.63 +				if (inputText.startsWith(MARKDOWN_HEADER)) {
    2.64 +					xhtml = readXhtmlTextMarkdown(inputText.substring(MARKDOWN_HEADER.length()));
    2.65 +				} else {
    2.66 +
    2.67 +					xhtml = readXhtmlText(
    2.68 +							inputText,
    2.69 +							getSubject(),
    2.70 +							getParentID(),
    2.71 +							null,
    2.72 +							null,
    2.73 +							null);
    2.74 +				}
    2.75  				return makeFragmentXHTML(xhtml);
    2.76  			} else {
    2.77  				throw new StorageBackendException("Only text/plain messages are supported for now – post it as plain text please.");