mirror of
https://github.com/lucaspalomodevelop/txtmark.git
synced 2026-03-12 23:37:22 +00:00
Adressed issue #23, unrelated formatting and style changes.
This commit is contained in:
parent
5e3322545c
commit
a933bf5f89
@ -17,25 +17,25 @@ package com.github.rjeschke.txtmark;
|
||||
|
||||
/**
|
||||
* This class represents a block of lines.
|
||||
*
|
||||
*
|
||||
* @author René Jeschke <rene_jeschke@yahoo.de>
|
||||
*/
|
||||
class Block
|
||||
{
|
||||
/** This block's type. */
|
||||
public BlockType type = BlockType.NONE;
|
||||
public BlockType type = BlockType.NONE;
|
||||
/** Head and tail of linked lines. */
|
||||
public Line lines = null, lineTail = null;
|
||||
public Line lines = null, lineTail = null;
|
||||
/** Head and tail of child blocks. */
|
||||
public Block blocks = null, blockTail = null;
|
||||
public Block blocks = null, blockTail = null;
|
||||
/** Next block. */
|
||||
public Block next = null;
|
||||
public Block next = null;
|
||||
/** Depth of headline BlockType. */
|
||||
public int hlDepth = 0;
|
||||
public int hlDepth = 0;
|
||||
/** ID for headlines and list items */
|
||||
public String id = null;
|
||||
public String id = null;
|
||||
/** Block meta information */
|
||||
public String meta = "";
|
||||
public String meta = "";
|
||||
|
||||
/** Constructor. */
|
||||
public Block()
|
||||
@ -56,7 +56,7 @@ class Block
|
||||
*/
|
||||
public void removeSurroundingEmptyLines()
|
||||
{
|
||||
if(this.lines != null)
|
||||
if (this.lines != null)
|
||||
{
|
||||
this.removeTrailingEmptyLines();
|
||||
this.removeLeadingEmptyLines();
|
||||
@ -68,31 +68,41 @@ class Block
|
||||
*/
|
||||
public void transfromHeadline()
|
||||
{
|
||||
if(this.hlDepth > 0)
|
||||
if (this.hlDepth > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int level = 0;
|
||||
final Line line = this.lines;
|
||||
if(line.isEmpty)
|
||||
if (line.isEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int start = line.leading;
|
||||
while(start < line.value.length() && line.value.charAt(start) == '#')
|
||||
while (start < line.value.length() && line.value.charAt(start) == '#')
|
||||
{
|
||||
level++;
|
||||
start++;
|
||||
}
|
||||
while(start < line.value.length() && line.value.charAt(start) == ' ')
|
||||
while (start < line.value.length() && line.value.charAt(start) == ' ')
|
||||
{
|
||||
start++;
|
||||
if(start >= line.value.length())
|
||||
}
|
||||
if (start >= line.value.length())
|
||||
{
|
||||
line.setEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
int end = line.value.length() - line.trailing - 1;
|
||||
while(line.value.charAt(end) == '#')
|
||||
while (line.value.charAt(end) == '#')
|
||||
{
|
||||
end--;
|
||||
while(line.value.charAt(end) == ' ')
|
||||
}
|
||||
while (line.value.charAt(end) == ' ')
|
||||
{
|
||||
end--;
|
||||
}
|
||||
line.value = line.value.substring(start, end + 1);
|
||||
line.leading = line.trailing = 0;
|
||||
}
|
||||
@ -101,18 +111,19 @@ class Block
|
||||
|
||||
/**
|
||||
* Used for nested lists. Removes list markers and up to 4 leading spaces.
|
||||
*
|
||||
* @param extendedMode
|
||||
* Whether extended profile ist activated or not
|
||||
*
|
||||
* @param configuration
|
||||
* txtmark configuration
|
||||
*
|
||||
*/
|
||||
public void removeListIndent(boolean extendedMode)
|
||||
public void removeListIndent(final Configuration configuration)
|
||||
{
|
||||
Line line = this.lines;
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
if(!line.isEmpty)
|
||||
if (!line.isEmpty)
|
||||
{
|
||||
switch(line.getLineType(extendedMode))
|
||||
switch (line.getLineType(configuration))
|
||||
{
|
||||
case ULIST:
|
||||
line.value = line.value.substring(line.leading + 2);
|
||||
@ -136,15 +147,17 @@ class Block
|
||||
public void removeBlockQuotePrefix()
|
||||
{
|
||||
Line line = this.lines;
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
if(!line.isEmpty)
|
||||
if (!line.isEmpty)
|
||||
{
|
||||
if(line.value.charAt(line.leading) == '>')
|
||||
if (line.value.charAt(line.leading) == '>')
|
||||
{
|
||||
int rem = line.leading + 1;
|
||||
if(line.leading + 1 < line.value.length() && line.value.charAt(line.leading + 1) == ' ')
|
||||
if (line.leading + 1 < line.value.length() && line.value.charAt(line.leading + 1) == ' ')
|
||||
{
|
||||
rem++;
|
||||
}
|
||||
line.value = line.value.substring(rem);
|
||||
line.initLeading();
|
||||
}
|
||||
@ -155,14 +168,14 @@ class Block
|
||||
|
||||
/**
|
||||
* Removes leading empty lines.
|
||||
*
|
||||
*
|
||||
* @return <code>true</code> if an empty line was removed.
|
||||
*/
|
||||
public boolean removeLeadingEmptyLines()
|
||||
{
|
||||
boolean wasEmpty = false;
|
||||
Line line = this.lines;
|
||||
while(line != null && line.isEmpty)
|
||||
while (line != null && line.isEmpty)
|
||||
{
|
||||
this.removeLine(line);
|
||||
line = this.lines;
|
||||
@ -177,7 +190,7 @@ class Block
|
||||
public void removeTrailingEmptyLines()
|
||||
{
|
||||
Line line = this.lineTail;
|
||||
while(line != null && line.isEmpty)
|
||||
while (line != null && line.isEmpty)
|
||||
{
|
||||
this.removeLine(line);
|
||||
line = this.lineTail;
|
||||
@ -187,7 +200,7 @@ class Block
|
||||
/**
|
||||
* Splits this block's lines, creating a new child block having 'line' as
|
||||
* it's lineTail.
|
||||
*
|
||||
*
|
||||
* @param line
|
||||
* The line to split from.
|
||||
* @return The newly created Block.
|
||||
@ -200,13 +213,19 @@ class Block
|
||||
block.lineTail = line;
|
||||
this.lines = line.next;
|
||||
line.next = null;
|
||||
if(this.lines == null)
|
||||
if (this.lines == null)
|
||||
{
|
||||
this.lineTail = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.lines.previous = null;
|
||||
}
|
||||
|
||||
if(this.blocks == null)
|
||||
if (this.blocks == null)
|
||||
{
|
||||
this.blocks = this.blockTail = block;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.blockTail.next = block;
|
||||
@ -218,33 +237,43 @@ class Block
|
||||
|
||||
/**
|
||||
* Removes the given line from this block.
|
||||
*
|
||||
*
|
||||
* @param line
|
||||
* Line to remove.
|
||||
*/
|
||||
public void removeLine(final Line line)
|
||||
{
|
||||
if(line.previous == null)
|
||||
if (line.previous == null)
|
||||
{
|
||||
this.lines = line.next;
|
||||
}
|
||||
else
|
||||
{
|
||||
line.previous.next = line.next;
|
||||
if(line.next == null)
|
||||
}
|
||||
if (line.next == null)
|
||||
{
|
||||
this.lineTail = line.previous;
|
||||
}
|
||||
else
|
||||
{
|
||||
line.next.previous = line.previous;
|
||||
}
|
||||
line.previous = line.next = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the given line to this block.
|
||||
*
|
||||
*
|
||||
* @param line
|
||||
* Line to append.
|
||||
*/
|
||||
public void appendLine(final Line line)
|
||||
{
|
||||
if(this.lineTail == null)
|
||||
if (this.lineTail == null)
|
||||
{
|
||||
this.lines = this.lineTail = line;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.lineTail.nextEmpty = line.isEmpty;
|
||||
@ -261,20 +290,20 @@ class Block
|
||||
*/
|
||||
public void expandListParagraphs()
|
||||
{
|
||||
if(this.type != BlockType.ORDERED_LIST && this.type != BlockType.UNORDERED_LIST)
|
||||
if (this.type != BlockType.ORDERED_LIST && this.type != BlockType.UNORDERED_LIST)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Block outer = this.blocks, inner;
|
||||
boolean hasParagraph = false;
|
||||
while(outer != null && !hasParagraph)
|
||||
while (outer != null && !hasParagraph)
|
||||
{
|
||||
if(outer.type == BlockType.LIST_ITEM)
|
||||
if (outer.type == BlockType.LIST_ITEM)
|
||||
{
|
||||
inner = outer.blocks;
|
||||
while(inner != null && !hasParagraph)
|
||||
while (inner != null && !hasParagraph)
|
||||
{
|
||||
if(inner.type == BlockType.PARAGRAPH)
|
||||
if (inner.type == BlockType.PARAGRAPH)
|
||||
{
|
||||
hasParagraph = true;
|
||||
}
|
||||
@ -283,17 +312,17 @@ class Block
|
||||
}
|
||||
outer = outer.next;
|
||||
}
|
||||
if(hasParagraph)
|
||||
if (hasParagraph)
|
||||
{
|
||||
outer = this.blocks;
|
||||
while(outer != null)
|
||||
while (outer != null)
|
||||
{
|
||||
if(outer.type == BlockType.LIST_ITEM)
|
||||
if (outer.type == BlockType.LIST_ITEM)
|
||||
{
|
||||
inner = outer.blocks;
|
||||
while(inner != null)
|
||||
while (inner != null)
|
||||
{
|
||||
if(inner.type == BlockType.NONE)
|
||||
if (inner.type == BlockType.NONE)
|
||||
{
|
||||
inner.type = BlockType.PARAGRAPH;
|
||||
}
|
||||
|
||||
@ -17,25 +17,26 @@ package com.github.rjeschke.txtmark;
|
||||
|
||||
/**
|
||||
* Txtmark configuration.
|
||||
*
|
||||
*
|
||||
* @author René Jeschke <rene_jeschke@yahoo.de>
|
||||
* @since 0.7
|
||||
*/
|
||||
public class Configuration
|
||||
{
|
||||
final boolean safeMode;
|
||||
final String encoding;
|
||||
final Decorator decorator;
|
||||
final BlockEmitter codeBlockEmitter;
|
||||
final boolean forceExtendedProfile;
|
||||
final SpanEmitter specialLinkEmitter;
|
||||
final boolean safeMode;
|
||||
final String encoding;
|
||||
final Decorator decorator;
|
||||
final BlockEmitter codeBlockEmitter;
|
||||
final boolean forceExtendedProfile;
|
||||
final boolean allowSpacesInFencedDelimiters;
|
||||
final SpanEmitter specialLinkEmitter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is the default configuration for txtmark's <code>process</code>
|
||||
* methods
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <ul>
|
||||
* <li><code>safeMode = false</code></li>
|
||||
* <li><code>encoding = UTF-8</code></li>
|
||||
@ -43,13 +44,13 @@ public class Configuration
|
||||
* <li><code>codeBlockEmitter = null</code></li>
|
||||
* </ul>
|
||||
*/
|
||||
public final static Configuration DEFAULT = Configuration.builder().build();
|
||||
public final static Configuration DEFAULT = Configuration.builder().build();
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Default safe configuration
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <ul>
|
||||
* <li><code>safeMode = true</code></li>
|
||||
* <li><code>encoding = UTF-8</code></li>
|
||||
@ -61,13 +62,15 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param safeMode
|
||||
* @param encoding
|
||||
* @param decorator
|
||||
*/
|
||||
Configuration(boolean safeMode, String encoding, Decorator decorator, BlockEmitter codeBlockEmitter,
|
||||
boolean forceExtendedProfile, SpanEmitter specialLinkEmitter)
|
||||
Configuration(final boolean safeMode, final String encoding, final Decorator decorator,
|
||||
final BlockEmitter codeBlockEmitter,
|
||||
final boolean forceExtendedProfile, final SpanEmitter specialLinkEmitter,
|
||||
final boolean allowSpacesInFencedDelimiters)
|
||||
{
|
||||
this.safeMode = safeMode;
|
||||
this.encoding = encoding;
|
||||
@ -75,11 +78,12 @@ public class Configuration
|
||||
this.codeBlockEmitter = codeBlockEmitter;
|
||||
this.forceExtendedProfile = forceExtendedProfile;
|
||||
this.specialLinkEmitter = specialLinkEmitter;
|
||||
this.allowSpacesInFencedDelimiters = allowSpacesInFencedDelimiters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Builder instance.
|
||||
*
|
||||
*
|
||||
* @return A new Builder instance.
|
||||
*/
|
||||
public static Builder builder()
|
||||
@ -89,22 +93,23 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Configuration builder.
|
||||
*
|
||||
*
|
||||
* @author René Jeschke <rene_jeschke@yahoo.de>
|
||||
* @since 0.7
|
||||
*/
|
||||
public static class Builder
|
||||
{
|
||||
private boolean safeMode = false;
|
||||
private boolean forceExtendedProfile = false;
|
||||
private String encoding = "UTF-8";
|
||||
private Decorator decorator = new DefaultDecorator();
|
||||
private BlockEmitter codeBlockEmitter = null;
|
||||
private SpanEmitter specialLinkEmitter = null;
|
||||
private boolean safeMode = false;
|
||||
private boolean forceExtendedProfile = false;
|
||||
private boolean allowSpacesInFencedDelimiters = true;
|
||||
private String encoding = "UTF-8";
|
||||
private Decorator decorator = new DefaultDecorator();
|
||||
private BlockEmitter codeBlockEmitter = null;
|
||||
private SpanEmitter specialLinkEmitter = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
*/
|
||||
Builder()
|
||||
{
|
||||
@ -113,9 +118,9 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Enables HTML safe mode.
|
||||
*
|
||||
*
|
||||
* Default: <code>false</code>
|
||||
*
|
||||
*
|
||||
* @return This builder
|
||||
* @since 0.7
|
||||
*/
|
||||
@ -127,7 +132,7 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Forces extened profile to be enabled by default.
|
||||
*
|
||||
*
|
||||
* @return This builder.
|
||||
* @since 0.7
|
||||
*/
|
||||
@ -139,15 +144,15 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Sets the HTML safe mode flag.
|
||||
*
|
||||
*
|
||||
* Default: <code>false</code>
|
||||
*
|
||||
*
|
||||
* @param flag
|
||||
* <code>true</code> to enable safe mode
|
||||
* @return This builder
|
||||
* @since 0.7
|
||||
*/
|
||||
public Builder setSafeMode(boolean flag)
|
||||
public Builder setSafeMode(final boolean flag)
|
||||
{
|
||||
this.safeMode = flag;
|
||||
return this;
|
||||
@ -155,15 +160,15 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Sets the character encoding for txtmark.
|
||||
*
|
||||
*
|
||||
* Default: <code>"UTF-8"</code>
|
||||
*
|
||||
*
|
||||
* @param encoding
|
||||
* The encoding
|
||||
* @return This builder
|
||||
* @since 0.7
|
||||
*/
|
||||
public Builder setEncoding(String encoding)
|
||||
public Builder setEncoding(final String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
return this;
|
||||
@ -171,16 +176,16 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Sets the decorator for txtmark.
|
||||
*
|
||||
*
|
||||
* Default: <code>DefaultDecorator()</code>
|
||||
*
|
||||
*
|
||||
* @param decorator
|
||||
* The decorator
|
||||
* @return This builder
|
||||
* @see DefaultDecorator
|
||||
* @since 0.7
|
||||
*/
|
||||
public Builder setDecorator(Decorator decorator)
|
||||
public Builder setDecorator(final Decorator decorator)
|
||||
{
|
||||
this.decorator = decorator;
|
||||
return this;
|
||||
@ -188,16 +193,16 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Sets the code block emitter.
|
||||
*
|
||||
*
|
||||
* Default: <code>null</code>
|
||||
*
|
||||
*
|
||||
* @param emitter
|
||||
* The BlockEmitter
|
||||
* @return This builder
|
||||
* @see BlockEmitter
|
||||
* @since 0.7
|
||||
*/
|
||||
public Builder setCodeBlockEmitter(BlockEmitter emitter)
|
||||
public Builder setCodeBlockEmitter(final BlockEmitter emitter)
|
||||
{
|
||||
this.codeBlockEmitter = emitter;
|
||||
return this;
|
||||
@ -205,28 +210,42 @@ public class Configuration
|
||||
|
||||
/**
|
||||
* Sets the emitter for special link spans ([[ ... ]]).
|
||||
*
|
||||
*
|
||||
* @param emitter
|
||||
* The emitter.
|
||||
* @return This builder.
|
||||
* @since 0.7
|
||||
*/
|
||||
public Builder setSpecialLinkEmitter(SpanEmitter emitter)
|
||||
public Builder setSpecialLinkEmitter(final SpanEmitter emitter)
|
||||
{
|
||||
this.specialLinkEmitter = emitter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Dis-)Allows spaces in fenced code block delimiter lines.
|
||||
*
|
||||
* @param allow
|
||||
* whether to allow or not
|
||||
* @return This builder.
|
||||
* @since 0.12
|
||||
*/
|
||||
public Builder setAllowSpacesInFencedCodeBlockDelimiters(final boolean allow)
|
||||
{
|
||||
this.allowSpacesInFencedDelimiters = allow;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a configuration instance.
|
||||
*
|
||||
*
|
||||
* @return a Configuration instance
|
||||
* @since 0.7
|
||||
*/
|
||||
public Configuration build()
|
||||
{
|
||||
return new Configuration(this.safeMode, this.encoding, this.decorator, this.codeBlockEmitter,
|
||||
this.forceExtendedProfile, this.specialLinkEmitter);
|
||||
this.forceExtendedProfile, this.specialLinkEmitter, this.allowSpacesInFencedDelimiters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,29 +19,29 @@ import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* This class represents a text line.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* It also provides methods for processing and analyzing a line.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author René Jeschke <rene_jeschke@yahoo.de>
|
||||
*/
|
||||
class Line
|
||||
{
|
||||
/** Current cursor position. */
|
||||
public int pos;
|
||||
public int pos;
|
||||
/** Leading and trailing spaces. */
|
||||
public int leading = 0, trailing = 0;
|
||||
public int leading = 0, trailing = 0;
|
||||
/** Is this line empty? */
|
||||
public boolean isEmpty = true;
|
||||
/** This line's value. */
|
||||
public String value = null;
|
||||
public String value = null;
|
||||
/** Previous and next line. */
|
||||
public Line previous = null, next = null;
|
||||
public Line previous = null, next = null;
|
||||
/** Is previous/next line empty? */
|
||||
public boolean prevEmpty, nextEmpty;
|
||||
/** Final line of a XML block. */
|
||||
public Line xmlEndLine;
|
||||
public Line xmlEndLine;
|
||||
|
||||
/** Constructor. */
|
||||
public Line()
|
||||
@ -55,10 +55,12 @@ class Line
|
||||
public void init()
|
||||
{
|
||||
this.leading = 0;
|
||||
while(this.leading < this.value.length() && this.value.charAt(this.leading) == ' ')
|
||||
while (this.leading < this.value.length() && this.value.charAt(this.leading) == ' ')
|
||||
{
|
||||
this.leading++;
|
||||
}
|
||||
|
||||
if(this.leading == this.value.length())
|
||||
if (this.leading == this.value.length())
|
||||
{
|
||||
this.setEmpty();
|
||||
}
|
||||
@ -66,8 +68,10 @@ class Line
|
||||
{
|
||||
this.isEmpty = false;
|
||||
this.trailing = 0;
|
||||
while(this.value.charAt(this.value.length() - this.trailing - 1) == ' ')
|
||||
while (this.value.charAt(this.value.length() - this.trailing - 1) == ' ')
|
||||
{
|
||||
this.trailing++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,10 +81,12 @@ class Line
|
||||
public void initLeading()
|
||||
{
|
||||
this.leading = 0;
|
||||
while(this.leading < this.value.length() && this.value.charAt(this.leading) == ' ')
|
||||
while (this.leading < this.value.length() && this.value.charAt(this.leading) == ' ')
|
||||
{
|
||||
this.leading++;
|
||||
}
|
||||
|
||||
if(this.leading == this.value.length())
|
||||
if (this.leading == this.value.length())
|
||||
{
|
||||
this.setEmpty();
|
||||
}
|
||||
@ -88,37 +94,39 @@ class Line
|
||||
|
||||
/**
|
||||
* Skips spaces.
|
||||
*
|
||||
*
|
||||
* @return <code>false</code> if end of line is reached
|
||||
*/
|
||||
// TODO use Util#skipSpaces
|
||||
public boolean skipSpaces()
|
||||
{
|
||||
while(this.pos < this.value.length() && this.value.charAt(this.pos) == ' ')
|
||||
while (this.pos < this.value.length() && this.value.charAt(this.pos) == ' ')
|
||||
{
|
||||
this.pos++;
|
||||
}
|
||||
return this.pos < this.value.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads chars from this line until any 'end' char is reached.
|
||||
*
|
||||
*
|
||||
* @param end
|
||||
* Delimiting character(s)
|
||||
* @return The read String or <code>null</code> if no 'end' char was
|
||||
* reached.
|
||||
*/
|
||||
// TODO use Util#readUntil
|
||||
public String readUntil(char... end)
|
||||
public String readUntil(final char... end)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
int pos = this.pos;
|
||||
while(pos < this.value.length())
|
||||
while (pos < this.value.length())
|
||||
{
|
||||
final char ch = this.value.charAt(pos);
|
||||
if(ch == '\\' && pos + 1 < this.value.length())
|
||||
if (ch == '\\' && pos + 1 < this.value.length())
|
||||
{
|
||||
final char c;
|
||||
switch(c = this.value.charAt(pos + 1))
|
||||
switch (c = this.value.charAt(pos + 1))
|
||||
{
|
||||
case '\\':
|
||||
case '[':
|
||||
@ -150,25 +158,27 @@ class Line
|
||||
else
|
||||
{
|
||||
boolean endReached = false;
|
||||
for(int n = 0; n < end.length; n++)
|
||||
for (int n = 0; n < end.length; n++)
|
||||
{
|
||||
if(ch == end[n])
|
||||
if (ch == end[n])
|
||||
{
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(endReached)
|
||||
if (endReached)
|
||||
{
|
||||
break;
|
||||
}
|
||||
sb.append(ch);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
final char ch = pos < this.value.length() ? this.value.charAt(pos) : '\n';
|
||||
for(int n = 0; n < end.length; n++)
|
||||
for (int n = 0; n < end.length; n++)
|
||||
{
|
||||
if(ch == end[n])
|
||||
if (ch == end[n])
|
||||
{
|
||||
this.pos = pos;
|
||||
return sb.toString();
|
||||
@ -185,28 +195,34 @@ class Line
|
||||
this.value = "";
|
||||
this.leading = this.trailing = 0;
|
||||
this.isEmpty = true;
|
||||
if(this.previous != null)
|
||||
if (this.previous != null)
|
||||
{
|
||||
this.previous.nextEmpty = true;
|
||||
if(this.next != null)
|
||||
}
|
||||
if (this.next != null)
|
||||
{
|
||||
this.next.prevEmpty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the amount of 'ch' in this line.
|
||||
*
|
||||
*
|
||||
* @param ch
|
||||
* The char to count.
|
||||
* @return A value > 0 if this line only consists of 'ch' end spaces.
|
||||
*/
|
||||
private int countChars(char ch)
|
||||
private int countChars(final char ch)
|
||||
{
|
||||
int count = 0;
|
||||
for(int i = 0; i < this.value.length(); i++)
|
||||
for (int i = 0; i < this.value.length(); i++)
|
||||
{
|
||||
final char c = this.value.charAt(i);
|
||||
if(c == ' ')
|
||||
if (c == ' ')
|
||||
{
|
||||
continue;
|
||||
if(c == ch)
|
||||
}
|
||||
if (c == ch)
|
||||
{
|
||||
count++;
|
||||
continue;
|
||||
@ -218,72 +234,98 @@ class Line
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the amount of 'ch' at the start of this line ignoring spaces.
|
||||
*
|
||||
* Counts the amount of 'ch' at the start of this line optionally ignoring
|
||||
* spaces.
|
||||
*
|
||||
* @param ch
|
||||
* The char to count.
|
||||
* @param allowSpaces
|
||||
* Whether to allow spaces or not
|
||||
* @return Number of characters found.
|
||||
* @since 0.7
|
||||
* @since 0.12
|
||||
*/
|
||||
private int countCharsStart(char ch)
|
||||
private int countCharsStart(final char ch, final boolean allowSpaces)
|
||||
{
|
||||
int count = 0;
|
||||
for(int i = 0; i < this.value.length(); i++)
|
||||
for (int i = 0; i < this.value.length(); i++)
|
||||
{
|
||||
final char c = this.value.charAt(i);
|
||||
if(c == ' ')
|
||||
if (c == ' ' && allowSpaces)
|
||||
{
|
||||
continue;
|
||||
if(c == ch)
|
||||
}
|
||||
if (c == ch)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this line's type.
|
||||
*
|
||||
* @param extendedMode
|
||||
* Whether extended profile is enabled or not
|
||||
*
|
||||
* @param configuration
|
||||
* txtmark configuration
|
||||
*
|
||||
* @return The LineType.
|
||||
*/
|
||||
public LineType getLineType(boolean extendedMode)
|
||||
public LineType getLineType(final Configuration configuration)
|
||||
{
|
||||
if(this.isEmpty)
|
||||
return LineType.EMPTY;
|
||||
|
||||
if(this.leading > 3)
|
||||
return LineType.CODE;
|
||||
|
||||
if(this.value.charAt(this.leading) == '#')
|
||||
return LineType.HEADLINE;
|
||||
|
||||
if(this.value.charAt(this.leading) == '>')
|
||||
return LineType.BQUOTE;
|
||||
|
||||
if(extendedMode)
|
||||
if (this.isEmpty)
|
||||
{
|
||||
if(this.value.length() - this.leading - this.trailing > 2)
|
||||
return LineType.EMPTY;
|
||||
}
|
||||
|
||||
if (this.leading > 3)
|
||||
{
|
||||
return LineType.CODE;
|
||||
}
|
||||
|
||||
if (this.value.charAt(this.leading) == '#')
|
||||
{
|
||||
return LineType.HEADLINE;
|
||||
}
|
||||
|
||||
if (this.value.charAt(this.leading) == '>')
|
||||
{
|
||||
return LineType.BQUOTE;
|
||||
}
|
||||
|
||||
if (configuration.forceExtendedProfile)
|
||||
{
|
||||
if (this.value.length() - this.leading - this.trailing > 2)
|
||||
{
|
||||
if(this.value.charAt(this.leading) == '`' && this.countCharsStart('`') >= 3)
|
||||
if (this.value.charAt(this.leading) == '`'
|
||||
&& this.countCharsStart('`', configuration.allowSpacesInFencedDelimiters) >= 3)
|
||||
{
|
||||
return LineType.FENCED_CODE;
|
||||
if(this.value.charAt(this.leading) == '~' && this.countCharsStart('~') >= 3)
|
||||
}
|
||||
if (this.value.charAt(this.leading) == '~'
|
||||
&& this.countCharsStart('~', configuration.allowSpacesInFencedDelimiters) >= 3)
|
||||
{
|
||||
return LineType.FENCED_CODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(this.value.length() - this.leading - this.trailing > 2
|
||||
if (this.value.length() - this.leading - this.trailing > 2
|
||||
&& (this.value.charAt(this.leading) == '*' || this.value.charAt(this.leading) == '-' || this.value
|
||||
.charAt(this.leading) == '_'))
|
||||
{
|
||||
if(this.countChars(this.value.charAt(this.leading)) >= 3)
|
||||
if (this.countChars(this.value.charAt(this.leading)) >= 3)
|
||||
{
|
||||
return LineType.HR;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.value.length() - this.leading >= 2 && this.value.charAt(this.leading + 1) == ' ')
|
||||
if (this.value.length() - this.leading >= 2 && this.value.charAt(this.leading + 1) == ' ')
|
||||
{
|
||||
switch(this.value.charAt(this.leading))
|
||||
switch (this.value.charAt(this.leading))
|
||||
{
|
||||
case '*':
|
||||
case '-':
|
||||
@ -292,27 +334,37 @@ class Line
|
||||
}
|
||||
}
|
||||
|
||||
if(this.value.length() - this.leading >= 3 && Character.isDigit(this.value.charAt(this.leading)))
|
||||
if (this.value.length() - this.leading >= 3 && Character.isDigit(this.value.charAt(this.leading)))
|
||||
{
|
||||
int i = this.leading + 1;
|
||||
while(i < this.value.length() && Character.isDigit(this.value.charAt(i)))
|
||||
while (i < this.value.length() && Character.isDigit(this.value.charAt(i)))
|
||||
{
|
||||
i++;
|
||||
if(i + 1 < this.value.length() && this.value.charAt(i) == '.' && this.value.charAt(i + 1) == ' ')
|
||||
}
|
||||
if (i + 1 < this.value.length() && this.value.charAt(i) == '.' && this.value.charAt(i + 1) == ' ')
|
||||
{
|
||||
return LineType.OLIST;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.value.charAt(this.leading) == '<')
|
||||
if (this.value.charAt(this.leading) == '<')
|
||||
{
|
||||
if(this.checkHTML())
|
||||
if (this.checkHTML())
|
||||
{
|
||||
return LineType.XML;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.next != null && !this.next.isEmpty)
|
||||
if (this.next != null && !this.next.isEmpty)
|
||||
{
|
||||
if((this.next.value.charAt(0) == '-') && (this.next.countChars('-') > 0))
|
||||
if ((this.next.value.charAt(0) == '-') && (this.next.countChars('-') > 0))
|
||||
{
|
||||
return LineType.HEADLINE2;
|
||||
if((this.next.value.charAt(0) == '=') && (this.next.countChars('=') > 0))
|
||||
}
|
||||
if ((this.next.value.charAt(0) == '=') && (this.next.countChars('=') > 0))
|
||||
{
|
||||
return LineType.HEADLINE1;
|
||||
}
|
||||
}
|
||||
|
||||
return LineType.OTHER;
|
||||
@ -320,7 +372,7 @@ class Line
|
||||
|
||||
/**
|
||||
* Reads an XML comment. Sets <code>xmlEndLine</code>.
|
||||
*
|
||||
*
|
||||
* @param firstLine
|
||||
* The Line to start reading from.
|
||||
* @param start
|
||||
@ -330,27 +382,27 @@ class Line
|
||||
private int readXMLComment(final Line firstLine, final int start)
|
||||
{
|
||||
Line line = firstLine;
|
||||
if(start + 3 < line.value.length())
|
||||
if (start + 3 < line.value.length())
|
||||
{
|
||||
if(line.value.charAt(2) == '-' && line.value.charAt(3) == '-')
|
||||
if (line.value.charAt(2) == '-' && line.value.charAt(3) == '-')
|
||||
{
|
||||
int pos = start + 4;
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
while(pos < line.value.length() && line.value.charAt(pos) != '-')
|
||||
while (pos < line.value.length() && line.value.charAt(pos) != '-')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
if(pos == line.value.length())
|
||||
if (pos == line.value.length())
|
||||
{
|
||||
line = line.next;
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pos + 2 < line.value.length())
|
||||
if (pos + 2 < line.value.length())
|
||||
{
|
||||
if(line.value.charAt(pos + 1) == '-' && line.value.charAt(pos + 2) == '>')
|
||||
if (line.value.charAt(pos + 1) == '-' && line.value.charAt(pos + 2) == '>')
|
||||
{
|
||||
this.xmlEndLine = line;
|
||||
return pos + 3;
|
||||
@ -367,24 +419,26 @@ class Line
|
||||
/**
|
||||
* Checks if this line contains an ID at it's end and removes it from the
|
||||
* line.
|
||||
*
|
||||
*
|
||||
* @return The ID or <code>null</code> if no valid ID exists.
|
||||
*/
|
||||
// FIXME ... hack
|
||||
public String stripID()
|
||||
{
|
||||
if(this.isEmpty || this.value.charAt(this.value.length() - this.trailing - 1) != '}')
|
||||
if (this.isEmpty || this.value.charAt(this.value.length() - this.trailing - 1) != '}')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int p = this.leading;
|
||||
boolean found = false;
|
||||
while(p < this.value.length() && !found)
|
||||
while (p < this.value.length() && !found)
|
||||
{
|
||||
switch(this.value.charAt(p))
|
||||
switch (this.value.charAt(p))
|
||||
{
|
||||
case '\\':
|
||||
if(p + 1 < this.value.length())
|
||||
if (p + 1 < this.value.length())
|
||||
{
|
||||
switch(this.value.charAt(p + 1))
|
||||
switch (this.value.charAt(p + 1))
|
||||
{
|
||||
case '{':
|
||||
p++;
|
||||
@ -402,21 +456,21 @@ class Line
|
||||
}
|
||||
}
|
||||
|
||||
if(found)
|
||||
if (found)
|
||||
{
|
||||
if(p + 1 < this.value.length() && this.value.charAt(p + 1) == '#')
|
||||
if (p + 1 < this.value.length() && this.value.charAt(p + 1) == '#')
|
||||
{
|
||||
final int start = p + 2;
|
||||
p = start;
|
||||
found = false;
|
||||
while(p < this.value.length() && !found)
|
||||
while (p < this.value.length() && !found)
|
||||
{
|
||||
switch(this.value.charAt(p))
|
||||
switch (this.value.charAt(p))
|
||||
{
|
||||
case '\\':
|
||||
if(p + 1 < this.value.length())
|
||||
if (p + 1 < this.value.length())
|
||||
{
|
||||
switch(this.value.charAt(p + 1))
|
||||
switch (this.value.charAt(p + 1))
|
||||
{
|
||||
case '}':
|
||||
p++;
|
||||
@ -433,10 +487,10 @@ class Line
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
if (found)
|
||||
{
|
||||
final String id = this.value.substring(start, p).trim();
|
||||
if(this.leading != 0)
|
||||
if (this.leading != 0)
|
||||
{
|
||||
this.value = this.value.substring(0, this.leading)
|
||||
+ this.value.substring(this.leading, start - 2).trim();
|
||||
@ -455,7 +509,7 @@ class Line
|
||||
|
||||
/**
|
||||
* Checks for a valid HTML block. Sets <code>xmlEndLine</code>.
|
||||
*
|
||||
*
|
||||
* @return <code>true</code> if it is a valid block.
|
||||
*/
|
||||
private boolean checkHTML()
|
||||
@ -463,22 +517,26 @@ class Line
|
||||
final LinkedList<String> tags = new LinkedList<String>();
|
||||
final StringBuilder temp = new StringBuilder();
|
||||
int pos = this.leading;
|
||||
if(this.value.charAt(this.leading + 1) == '!')
|
||||
if (this.value.charAt(this.leading + 1) == '!')
|
||||
{
|
||||
if(this.readXMLComment(this, this.leading) > 0)
|
||||
if (this.readXMLComment(this, this.leading) > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pos = Utils.readXML(temp, this.value, this.leading, false);
|
||||
String element, tag;
|
||||
if(pos > -1)
|
||||
if (pos > -1)
|
||||
{
|
||||
element = temp.toString();
|
||||
temp.setLength(0);
|
||||
Utils.getXMLTag(temp, element);
|
||||
tag = temp.toString().toLowerCase();
|
||||
if(!HTML.isHtmlBlockElement(tag))
|
||||
if (!HTML.isHtmlBlockElement(tag))
|
||||
{
|
||||
return false;
|
||||
if(tag.equals("hr"))
|
||||
}
|
||||
if (tag.equals("hr"))
|
||||
{
|
||||
this.xmlEndLine = this;
|
||||
return true;
|
||||
@ -486,13 +544,13 @@ class Line
|
||||
tags.add(tag);
|
||||
|
||||
Line line = this;
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
while(pos < line.value.length() && line.value.charAt(pos) != '<')
|
||||
while (pos < line.value.length() && line.value.charAt(pos) != '<')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
if(pos >= line.value.length())
|
||||
if (pos >= line.value.length())
|
||||
{
|
||||
line = line.next;
|
||||
pos = 0;
|
||||
@ -501,18 +559,20 @@ class Line
|
||||
{
|
||||
temp.setLength(0);
|
||||
final int newPos = Utils.readXML(temp, line.value, pos, false);
|
||||
if(newPos > 0)
|
||||
if (newPos > 0)
|
||||
{
|
||||
element = temp.toString();
|
||||
temp.setLength(0);
|
||||
Utils.getXMLTag(temp, element);
|
||||
tag = temp.toString().toLowerCase();
|
||||
if(HTML.isHtmlBlockElement(tag) && !tag.equals("hr"))
|
||||
if (HTML.isHtmlBlockElement(tag) && !tag.equals("hr"))
|
||||
{
|
||||
if(element.charAt(1) == '/')
|
||||
if (element.charAt(1) == '/')
|
||||
{
|
||||
if(!tags.getLast().equals(tag))
|
||||
if (!tags.getLast().equals(tag))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tags.removeLast();
|
||||
}
|
||||
else
|
||||
@ -520,7 +580,7 @@ class Line
|
||||
tags.addLast(tag);
|
||||
}
|
||||
}
|
||||
if(tags.size() == 0)
|
||||
if (tags.size() == 0)
|
||||
{
|
||||
this.xmlEndLine = line;
|
||||
break;
|
||||
|
||||
@ -26,32 +26,32 @@ import java.io.StringReader;
|
||||
|
||||
/**
|
||||
* Markdown processor class.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* <code>String result = Processor.process("This is ***TXTMARK***");
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author René Jeschke <rene_jeschke@yahoo.de>
|
||||
*/
|
||||
public class Processor
|
||||
{
|
||||
/** The reader. */
|
||||
private final Reader reader;
|
||||
private final Reader reader;
|
||||
/** The emitter. */
|
||||
private final Emitter emitter;
|
||||
/** The Configuration. */
|
||||
final Configuration config;
|
||||
final Configuration config;
|
||||
/** Extension flag. */
|
||||
private boolean useExtensions = false;
|
||||
private boolean useExtensions = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param reader
|
||||
* The input reader.
|
||||
*/
|
||||
@ -65,7 +65,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML using the given Configuration.
|
||||
*
|
||||
*
|
||||
* @param reader
|
||||
* The Reader to process.
|
||||
* @param configuration
|
||||
@ -85,7 +85,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input String into HTML using the given Configuration.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The String to process.
|
||||
* @param configuration
|
||||
@ -100,7 +100,7 @@ public class Processor
|
||||
{
|
||||
return process(new StringReader(input), configuration);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
// This _can never_ happen
|
||||
return null;
|
||||
@ -109,9 +109,11 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML using the given Configuration.
|
||||
*
|
||||
* @param file The File to process.
|
||||
* @param configuration the Configuration
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param configuration
|
||||
* the Configuration
|
||||
* @return The processed String.
|
||||
* @throws IOException
|
||||
* if an IO error occurs
|
||||
@ -128,7 +130,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML using the given Configuration.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param configuration
|
||||
@ -148,7 +150,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input String into HTML using the default Configuration.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The String to process.
|
||||
* @return The processed String.
|
||||
@ -161,7 +163,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input String into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The String to process.
|
||||
* @param safeMode
|
||||
@ -176,7 +178,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input String into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The String to process.
|
||||
* @param decorator
|
||||
@ -191,7 +193,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input String into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The String to process.
|
||||
* @param decorator
|
||||
@ -208,7 +210,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML using the default Configuration.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @return The processed String.
|
||||
@ -223,7 +225,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param safeMode
|
||||
@ -240,7 +242,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param decorator
|
||||
@ -257,7 +259,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param decorator
|
||||
@ -277,7 +279,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param encoding
|
||||
@ -294,7 +296,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param encoding
|
||||
@ -314,7 +316,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param encoding
|
||||
@ -334,7 +336,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input file into HTML.
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
* The File to process.
|
||||
* @param encoding
|
||||
@ -357,7 +359,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @return The processed String.
|
||||
@ -372,7 +374,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param safeMode
|
||||
@ -389,7 +391,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param decorator
|
||||
@ -406,7 +408,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param decorator
|
||||
@ -426,7 +428,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param encoding
|
||||
@ -443,7 +445,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param encoding
|
||||
@ -463,7 +465,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param encoding
|
||||
@ -483,7 +485,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* The InputStream to process.
|
||||
* @param encoding
|
||||
@ -506,7 +508,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML using the default Configuration.
|
||||
*
|
||||
*
|
||||
* @param reader
|
||||
* The Reader to process.
|
||||
* @return The processed String.
|
||||
@ -521,7 +523,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param reader
|
||||
* The Reader to process.
|
||||
* @param safeMode
|
||||
@ -538,7 +540,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param reader
|
||||
* The Reader to process.
|
||||
* @param decorator
|
||||
@ -555,7 +557,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Transforms an input stream into HTML.
|
||||
*
|
||||
*
|
||||
* @param reader
|
||||
* The Reader to process.
|
||||
* @param decorator
|
||||
@ -578,7 +580,7 @@ public class Processor
|
||||
* <p>
|
||||
* Takes care of markdown link references.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return A Block containing all lines.
|
||||
* @throws IOException
|
||||
* If an IO error occurred.
|
||||
@ -589,34 +591,38 @@ public class Processor
|
||||
final StringBuilder sb = new StringBuilder(80);
|
||||
int c = this.reader.read();
|
||||
LinkRef lastLinkRef = null;
|
||||
while(c != -1)
|
||||
while (c != -1)
|
||||
{
|
||||
sb.setLength(0);
|
||||
int pos = 0;
|
||||
boolean eol = false;
|
||||
while(!eol)
|
||||
while (!eol)
|
||||
{
|
||||
switch(c)
|
||||
switch (c)
|
||||
{
|
||||
case -1:
|
||||
eol = true;
|
||||
break;
|
||||
case '\n':
|
||||
c = this.reader.read();
|
||||
if(c == '\r')
|
||||
if (c == '\r')
|
||||
{
|
||||
c = this.reader.read();
|
||||
}
|
||||
eol = true;
|
||||
break;
|
||||
case '\r':
|
||||
c = this.reader.read();
|
||||
if(c == '\n')
|
||||
if (c == '\n')
|
||||
{
|
||||
c = this.reader.read();
|
||||
}
|
||||
eol = true;
|
||||
break;
|
||||
case '\t':
|
||||
{
|
||||
final int np = pos + (4 - (pos & 3));
|
||||
while(pos < np)
|
||||
while (pos < np)
|
||||
{
|
||||
sb.append(' ');
|
||||
pos++;
|
||||
@ -639,57 +645,63 @@ public class Processor
|
||||
// Check for link definitions
|
||||
boolean isLinkRef = false;
|
||||
String id = null, link = null, comment = null;
|
||||
if(!line.isEmpty && line.leading < 4 && line.value.charAt(line.leading) == '[')
|
||||
if (!line.isEmpty && line.leading < 4 && line.value.charAt(line.leading) == '[')
|
||||
{
|
||||
line.pos = line.leading + 1;
|
||||
// Read ID up to ']'
|
||||
id = line.readUntil(']');
|
||||
// Is ID valid and are there any more characters?
|
||||
if(id != null && line.pos + 2 < line.value.length())
|
||||
if (id != null && line.pos + 2 < line.value.length())
|
||||
{
|
||||
// Check for ':' ([...]:...)
|
||||
if(line.value.charAt(line.pos + 1) == ':')
|
||||
if (line.value.charAt(line.pos + 1) == ':')
|
||||
{
|
||||
line.pos += 2;
|
||||
line.skipSpaces();
|
||||
// Check for link syntax
|
||||
if(line.value.charAt(line.pos) == '<')
|
||||
if (line.value.charAt(line.pos) == '<')
|
||||
{
|
||||
line.pos++;
|
||||
link = line.readUntil('>');
|
||||
line.pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
link = line.readUntil(' ', '\n');
|
||||
}
|
||||
|
||||
// Is link valid?
|
||||
if(link != null)
|
||||
if (link != null)
|
||||
{
|
||||
// Any non-whitespace characters following?
|
||||
if(line.skipSpaces())
|
||||
if (line.skipSpaces())
|
||||
{
|
||||
final char ch = line.value.charAt(line.pos);
|
||||
// Read comment
|
||||
if(ch == '\"' || ch == '\'' || ch == '(')
|
||||
if (ch == '\"' || ch == '\'' || ch == '(')
|
||||
{
|
||||
line.pos++;
|
||||
comment = line.readUntil(ch == '(' ? ')' : ch);
|
||||
// Valid linkRef only if comment is valid
|
||||
if(comment != null)
|
||||
if (comment != null)
|
||||
{
|
||||
isLinkRef = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isLinkRef = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To make compiler happy: add != null checks
|
||||
if(isLinkRef && id != null && link != null)
|
||||
if (isLinkRef && id != null && link != null)
|
||||
{
|
||||
if(id.toLowerCase().equals("$profile$"))
|
||||
if (id.toLowerCase().equals("$profile$"))
|
||||
{
|
||||
this.emitter.useExtensions = this.useExtensions = link.toLowerCase().equals("extended");
|
||||
lastLinkRef = null;
|
||||
@ -700,31 +712,35 @@ public class Processor
|
||||
final LinkRef lr = new LinkRef(link, comment, comment != null
|
||||
&& (link.length() == 1 && link.charAt(0) == '*'));
|
||||
this.emitter.addLinkRef(id, lr);
|
||||
if(comment == null)
|
||||
if (comment == null)
|
||||
{
|
||||
lastLinkRef = lr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
comment = null;
|
||||
// Check for multi-line linkRef
|
||||
if(!line.isEmpty && lastLinkRef != null)
|
||||
if (!line.isEmpty && lastLinkRef != null)
|
||||
{
|
||||
line.pos = line.leading;
|
||||
final char ch = line.value.charAt(line.pos);
|
||||
if(ch == '\"' || ch == '\'' || ch == '(')
|
||||
if (ch == '\"' || ch == '\'' || ch == '(')
|
||||
{
|
||||
line.pos++;
|
||||
comment = line.readUntil(ch == '(' ? ')' : ch);
|
||||
}
|
||||
if(comment != null)
|
||||
if (comment != null)
|
||||
{
|
||||
lastLinkRef.title = comment;
|
||||
}
|
||||
|
||||
lastLinkRef = null;
|
||||
}
|
||||
|
||||
// No multi-line linkRef, store line
|
||||
if(comment == null)
|
||||
if (comment == null)
|
||||
{
|
||||
line.pos = 0;
|
||||
block.appendLine(line);
|
||||
@ -737,7 +753,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Initializes a list block by separating it into list item blocks.
|
||||
*
|
||||
*
|
||||
* @param root
|
||||
* The Block to process.
|
||||
*/
|
||||
@ -745,10 +761,10 @@ public class Processor
|
||||
{
|
||||
Line line = root.lines;
|
||||
line = line.next;
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
final LineType t = line.getLineType(this.useExtensions);
|
||||
if((t == LineType.OLIST || t == LineType.ULIST)
|
||||
final LineType t = line.getLineType(this.config);
|
||||
if ((t == LineType.OLIST || t == LineType.ULIST)
|
||||
|| (!line.isEmpty && (line.prevEmpty && line.leading == 0 && !(t == LineType.OLIST || t == LineType.ULIST))))
|
||||
{
|
||||
root.split(line.previous).type = BlockType.LIST_ITEM;
|
||||
@ -760,53 +776,64 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Recursively process the given Block.
|
||||
*
|
||||
*
|
||||
* @param root
|
||||
* The Block to process.
|
||||
* @param listMode
|
||||
* Flag indicating that we're in a list item block.
|
||||
*/
|
||||
private void recurse(final Block root, boolean listMode)
|
||||
private void recurse(final Block root, final boolean listMode)
|
||||
{
|
||||
Block block, list;
|
||||
Line line = root.lines;
|
||||
|
||||
if(listMode)
|
||||
if (listMode)
|
||||
{
|
||||
root.removeListIndent(this.useExtensions);
|
||||
if(this.useExtensions && root.lines != null && root.lines.getLineType(this.useExtensions) != LineType.CODE)
|
||||
root.removeListIndent(this.config);
|
||||
if (this.useExtensions && root.lines != null && root.lines.getLineType(this.config) != LineType.CODE)
|
||||
{
|
||||
root.id = root.lines.stripID();
|
||||
}
|
||||
}
|
||||
|
||||
while(line != null && line.isEmpty)
|
||||
line = line.next;
|
||||
if(line == null)
|
||||
return;
|
||||
|
||||
while(line != null)
|
||||
while (line != null && line.isEmpty)
|
||||
{
|
||||
final LineType type = line.getLineType(this.useExtensions);
|
||||
switch(type)
|
||||
line = line.next;
|
||||
}
|
||||
if (line == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (line != null)
|
||||
{
|
||||
final LineType type = line.getLineType(this.config);
|
||||
switch (type)
|
||||
{
|
||||
case OTHER:
|
||||
{
|
||||
final boolean wasEmpty = line.prevEmpty;
|
||||
while(line != null && !line.isEmpty)
|
||||
while (line != null && !line.isEmpty)
|
||||
{
|
||||
final LineType t = line.getLineType(this.useExtensions);
|
||||
if((listMode || this.useExtensions) && (t == LineType.OLIST || t == LineType.ULIST))
|
||||
final LineType t = line.getLineType(this.config);
|
||||
if ((listMode || this.useExtensions) && (t == LineType.OLIST || t == LineType.ULIST))
|
||||
{
|
||||
break;
|
||||
if(this.useExtensions && (t == LineType.CODE || t == LineType.FENCED_CODE))
|
||||
}
|
||||
if (this.useExtensions && (t == LineType.CODE || t == LineType.FENCED_CODE))
|
||||
{
|
||||
break;
|
||||
if(t == LineType.HEADLINE || t == LineType.HEADLINE1 || t == LineType.HEADLINE2 || t == LineType.HR
|
||||
}
|
||||
if (t == LineType.HEADLINE || t == LineType.HEADLINE1 || t == LineType.HEADLINE2
|
||||
|| t == LineType.HR
|
||||
|| t == LineType.BQUOTE || t == LineType.XML)
|
||||
{
|
||||
break;
|
||||
}
|
||||
line = line.next;
|
||||
}
|
||||
final BlockType bt;
|
||||
if(line != null && !line.isEmpty)
|
||||
if (line != null && !line.isEmpty)
|
||||
{
|
||||
bt = (listMode && !wasEmpty) ? BlockType.NONE : BlockType.PARAGRAPH;
|
||||
root.split(line.previous).type = bt;
|
||||
@ -823,7 +850,7 @@ public class Processor
|
||||
break;
|
||||
}
|
||||
case CODE:
|
||||
while(line != null && (line.isEmpty || line.leading > 3))
|
||||
while (line != null && (line.isEmpty || line.leading > 3))
|
||||
{
|
||||
line = line.next;
|
||||
}
|
||||
@ -832,7 +859,7 @@ public class Processor
|
||||
block.removeSurroundingEmptyLines();
|
||||
break;
|
||||
case XML:
|
||||
if(line.previous != null)
|
||||
if (line.previous != null)
|
||||
{
|
||||
// FIXME ... this looks wrong
|
||||
root.split(line.previous);
|
||||
@ -842,11 +869,13 @@ public class Processor
|
||||
line = root.lines;
|
||||
break;
|
||||
case BQUOTE:
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
if(!line.isEmpty
|
||||
&& (line.prevEmpty && line.leading == 0 && line.getLineType(this.useExtensions) != LineType.BQUOTE))
|
||||
if (!line.isEmpty
|
||||
&& (line.prevEmpty && line.leading == 0 && line.getLineType(this.config) != LineType.BQUOTE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
line = line.next;
|
||||
}
|
||||
block = root.split(line != null ? line.previous : root.lineTail);
|
||||
@ -857,7 +886,7 @@ public class Processor
|
||||
line = root.lines;
|
||||
break;
|
||||
case HR:
|
||||
if(line.previous != null)
|
||||
if (line.previous != null)
|
||||
{
|
||||
// FIXME ... this looks wrong
|
||||
root.split(line.previous);
|
||||
@ -868,53 +897,65 @@ public class Processor
|
||||
break;
|
||||
case FENCED_CODE:
|
||||
line = line.next;
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
if(line.getLineType(this.useExtensions) == LineType.FENCED_CODE)
|
||||
if (line.getLineType(this.config) == LineType.FENCED_CODE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// TODO ... is this really necessary? Maybe add a special
|
||||
// flag?
|
||||
line = line.next;
|
||||
}
|
||||
if(line != null)
|
||||
if (line != null)
|
||||
{
|
||||
line = line.next;
|
||||
}
|
||||
block = root.split(line != null ? line.previous : root.lineTail);
|
||||
block.type = BlockType.FENCED_CODE;
|
||||
block.meta = Utils.getMetaFromFence(block.lines.value);
|
||||
block.lines.setEmpty();
|
||||
if(block.lineTail.getLineType(this.useExtensions) == LineType.FENCED_CODE)
|
||||
if (block.lineTail.getLineType(this.config) == LineType.FENCED_CODE)
|
||||
{
|
||||
block.lineTail.setEmpty();
|
||||
}
|
||||
block.removeSurroundingEmptyLines();
|
||||
break;
|
||||
case HEADLINE:
|
||||
case HEADLINE1:
|
||||
case HEADLINE2:
|
||||
if(line.previous != null)
|
||||
if (line.previous != null)
|
||||
{
|
||||
root.split(line.previous);
|
||||
}
|
||||
if(type != LineType.HEADLINE)
|
||||
if (type != LineType.HEADLINE)
|
||||
{
|
||||
line.next.setEmpty();
|
||||
}
|
||||
block = root.split(line);
|
||||
block.type = BlockType.HEADLINE;
|
||||
if(type != LineType.HEADLINE)
|
||||
if (type != LineType.HEADLINE)
|
||||
{
|
||||
block.hlDepth = type == LineType.HEADLINE1 ? 1 : 2;
|
||||
if(this.useExtensions)
|
||||
}
|
||||
if (this.useExtensions)
|
||||
{
|
||||
block.id = block.lines.stripID();
|
||||
}
|
||||
block.transfromHeadline();
|
||||
root.removeLeadingEmptyLines();
|
||||
line = root.lines;
|
||||
break;
|
||||
case OLIST:
|
||||
case ULIST:
|
||||
while(line != null)
|
||||
while (line != null)
|
||||
{
|
||||
final LineType t = line.getLineType(this.useExtensions);
|
||||
if(!line.isEmpty
|
||||
final LineType t = line.getLineType(this.config);
|
||||
if (!line.isEmpty
|
||||
&& (line.prevEmpty && line.leading == 0 && !(t == LineType.OLIST || t == LineType.ULIST)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
line = line.next;
|
||||
}
|
||||
list = root.split(line != null ? line.previous : root.lineTail);
|
||||
@ -923,9 +964,9 @@ public class Processor
|
||||
list.lineTail.nextEmpty = false;
|
||||
list.removeSurroundingEmptyLines();
|
||||
list.lines.prevEmpty = list.lineTail.nextEmpty = false;
|
||||
initListBlock(list);
|
||||
this.initListBlock(list);
|
||||
block = list.blocks;
|
||||
while(block != null)
|
||||
while (block != null)
|
||||
{
|
||||
this.recurse(block, true);
|
||||
block = block.next;
|
||||
@ -941,7 +982,7 @@ public class Processor
|
||||
|
||||
/**
|
||||
* Does all the processing.
|
||||
*
|
||||
*
|
||||
* @return The processed String.
|
||||
* @throws IOException
|
||||
* If an IO error occurred.
|
||||
@ -954,7 +995,7 @@ public class Processor
|
||||
|
||||
this.recurse(parent, false);
|
||||
Block block = parent.blocks;
|
||||
while(block != null)
|
||||
while (block != null)
|
||||
{
|
||||
this.emitter.emit(out, block);
|
||||
block = block.next;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user