Skip to content

Commit 6169a1c

Browse files
authored
Merge pull request #11 from Softwee/feature/highlight.markdown
Added Markdown support
2 parents f6f8ab5 + 64b3269 commit 6169a1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4356
-23
lines changed

codeview/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ dependencies {
2727
testCompile 'junit:junit:4.12'
2828

2929
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
30-
compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '1.0.3'
3130

3231
compile 'com.android.support:appcompat-v7:24.2.0'
3332
compile 'com.android.support:recyclerview-v7:24.2.0'
34-
compile 'com.github.twalcari:java-prettify:1.2.2'
3533
}
3634
repositories {
3735
mavenCentral()

codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class CodeView : RelativeLayout {
111111
return rvCodeContent.adapter as AbstractCodeAdapter<*>
112112
}
113113
set(adapter) {
114-
delayed { // to prevent UI overhead & initialization inconsistency
114+
delayed { // prevent UI overhead & initialization inconsistency
115115
rvCodeContent.adapter = adapter
116116
state = ViewState.PRESENTED
117117
}

codeview/src/main/java/io/github/kbiakov/codeview/highlight/CodeHighlighter.kt

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package io.github.kbiakov.codeview.highlight
22

33
import android.graphics.Color
4-
import prettify.PrettifyParser
5-
import syntaxhighlight.ParseResult
4+
import io.github.kbiakov.codeview.highlight.prettify.PrettifyParser
5+
import io.github.kbiakov.codeview.highlight.parser.ParseResult
66
import java.util.*
77

88
/**
@@ -34,9 +34,9 @@ object CodeHighlighter {
3434
val highlighted = StringBuilder()
3535

3636
results.forEach { result ->
37-
val color = getColor(colorsMap, result)
37+
val color = colorsMap.getColor(result)
3838
val content = parseContent(source, result)
39-
highlighted.append("<font color=\"$color\">$content</font>")
39+
highlighted.append(content.withFontParams(color))
4040
}
4141

4242
return highlighted.toString()
@@ -60,12 +60,11 @@ object CodeHighlighter {
6060
/**
6161
* Color accessor from built color map for selected color theme.
6262
*
63-
* @param colorsMap Colors map built from color theme
6463
* @param result Syntax unit
6564
* @return Color for syntax unit
6665
*/
67-
private fun getColor(colorsMap: HashMap<String, String>, result: ParseResult) =
68-
colorsMap[result.styleKeys[0]] ?: colorsMap["pln"]
66+
private fun HashMap<String, String>.getColor(result: ParseResult) =
67+
this[result.styleKeys[0]] ?: this["pln"]
6968

7069
/**
7170
* Build fast accessor (as map) for selected color theme.
@@ -200,9 +199,7 @@ data class SyntaxColors(
200199
val attrValue: Int = 0x269186)
201200

202201
/**
203-
* Convert hex int to color by adding alpha-channel.
204-
*
205-
* @return Color int
202+
* @return Converted hex int to color by adding alpha-channel
206203
*/
207204
fun Int.color() = try {
208205
Color.parseColor("#FF${Integer.toHexString(this)}")
@@ -211,8 +208,55 @@ fun Int.color() = try {
211208
}
212209

213210
/**
214-
* Convert hex int to hex string.
215-
*
216-
* @return Hex string
211+
* @return Converted hex int to hex string
217212
*/
218213
fun Int.hex() = "#${Integer.toHexString(this)}"
214+
215+
/**
216+
* @return Is value equals to found or not condition
217+
*/
218+
fun Int.isFound() = this >= 0
219+
fun Int.notFound() = this == -1
220+
221+
/**
222+
* @return String with applied font params
223+
*/
224+
fun String.withFontParams(color: String?): String {
225+
val parametrizedString = StringBuilder()
226+
227+
var idx = 0
228+
var newIdx = indexOf("\n")
229+
230+
if (newIdx.notFound()) // covers expected tag coverage (within only one line)
231+
parametrizedString.append(inFontTag(color))
232+
else { // may contain multiple lines with line breaks
233+
234+
// put tag on the borders (end & start of line, ..., end of tag)
235+
while (newIdx.isFound()) { // until closing tag is reached
236+
val part = substring(idx..newIdx).inFontTag(color)
237+
parametrizedString.append(part)
238+
239+
idx = newIdx
240+
newIdx = indexOf("\n", idx + 1)
241+
}
242+
243+
if (idx != indexOf("\n")) // if not replaced only once (for multiline tag coverage)
244+
parametrizedString.append(substring(idx).inFontTag(color))
245+
}
246+
247+
return parametrizedString.toString()
248+
}
249+
250+
/**
251+
* @return String with escaped line break at start
252+
*/
253+
fun String.escLineBreakAtStart() =
254+
if (startsWith("\n") && length >= 2)
255+
substring(1)
256+
else this
257+
258+
/**
259+
* @return String surrounded by font tag
260+
*/
261+
fun String.inFontTag(color: String?) =
262+
"<font color=\"$color\">${escLineBreakAtStart()}</font>"
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright (c) 2012 Chan Wai Shing
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining
4+
// a copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to
8+
// permit persons to whom the Software is furnished to do so, subject to
9+
// the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be
12+
// included in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
package io.github.kbiakov.codeview.highlight.parser;
22+
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
26+
/**
27+
* The parser parsed result.
28+
*
29+
* This class include the information needed to highlight the syntax.
30+
* Information includes where the content located in the document (offset and
31+
* length) and what style(s) should be applied on that segment of content.
32+
*
33+
* @author Chan Wai Shing <cws1989@gmail.com>
34+
*/
35+
public class ParseResult {
36+
37+
/**
38+
* The start position of the content.
39+
*/
40+
protected int offset;
41+
/**
42+
* The length of the content.
43+
*/
44+
protected int length;
45+
/**
46+
* The style keys of the content. The style at higher index of the list will
47+
* override the style of the lower index.
48+
*/
49+
protected List<String> styleKeys;
50+
51+
/**
52+
* Constructor.
53+
*
54+
* @param offset the start position of the content
55+
* @param length the length of the content
56+
* @param styleKeys the style keys of the content
57+
*/
58+
public ParseResult(int offset, int length, List<String> styleKeys) {
59+
this.offset = offset;
60+
this.length = length;
61+
this.styleKeys = new ArrayList<String>(styleKeys);
62+
}
63+
64+
/**
65+
* The start position of the content.
66+
* @return the start position of the content
67+
*/
68+
public int getOffset() {
69+
return offset;
70+
}
71+
72+
/**
73+
* The start position of the content.
74+
* @param offset the start position of the content
75+
*/
76+
public void setOffset(int offset) {
77+
this.offset = offset;
78+
}
79+
80+
/**
81+
* The length of the content.
82+
* @return the length of the content
83+
*/
84+
public int getLength() {
85+
return length;
86+
}
87+
88+
/**
89+
* The length of the content.
90+
* @param length the length of the content
91+
*/
92+
public void setLength(int length) {
93+
this.length = length;
94+
}
95+
96+
/**
97+
* Get the style keys represented by one string key, see
98+
* {@link Theme#getStylesAttributeSet(String)}.
99+
* @return the style keys of the content
100+
*/
101+
public String getStyleKeysString() {
102+
StringBuilder sb = new StringBuilder(10);
103+
for (int i = 0, iEnd = styleKeys.size(); i < iEnd; i++) {
104+
if (i != 0) {
105+
sb.append(" ");
106+
}
107+
sb.append(styleKeys.get(i));
108+
}
109+
return sb.toString();
110+
}
111+
112+
/**
113+
* The style keys of the content.
114+
* @param styleKeys the style keys of the content
115+
*/
116+
public void setStyleKeys(List<String> styleKeys) {
117+
this.styleKeys = new ArrayList<String>(styleKeys);
118+
}
119+
120+
/**
121+
* The style keys of the content.
122+
* @param styleKey the style key
123+
* @return see the return value of {@link List#add(Object)}
124+
*/
125+
public boolean addStyleKey(String styleKey) {
126+
return styleKeys.add(styleKey);
127+
}
128+
129+
/**
130+
* The style keys of the content.
131+
* @param styleKey the style key
132+
* @return see the return value of {@link List#remove(Object)}
133+
*/
134+
public boolean removeStyleKey(String styleKey) {
135+
return styleKeys.remove(styleKey);
136+
}
137+
138+
/**
139+
* The style keys of the content.
140+
*/
141+
public void clearStyleKeys() {
142+
styleKeys.clear();
143+
}
144+
145+
/**
146+
* The style keys for this matched result, see {@link syntaxhighlighter.theme}.
147+
* @return the style keys
148+
*/
149+
public List<String> getStyleKeys() {
150+
return new ArrayList<String>(styleKeys);
151+
}
152+
153+
/**
154+
* {@inheritDoc}
155+
*/
156+
@Override
157+
public String toString() {
158+
StringBuilder sb = new StringBuilder();
159+
160+
sb.append("[");
161+
sb.append(offset);
162+
sb.append("; ");
163+
sb.append(length);
164+
sb.append("; ");
165+
for (int i = 0, iEnd = styleKeys.size(); i < iEnd; i++) {
166+
if (i != 0) {
167+
sb.append(", ");
168+
}
169+
sb.append(styleKeys.get(i));
170+
}
171+
sb.append("]");
172+
173+
return sb.toString();
174+
}
175+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) 2012 Chan Wai Shing
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining
4+
// a copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to
8+
// permit persons to whom the Software is furnished to do so, subject to
9+
// the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be
12+
// included in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
package io.github.kbiakov.codeview.highlight.parser;
22+
23+
import java.util.List;
24+
25+
/**
26+
* The parser for syntax highlight.
27+
*
28+
* @author Chan Wai Shing <cws1989@gmail.com>
29+
*/
30+
public interface Parser {
31+
32+
/**
33+
* Parse the {@code content} and return the parsed result.
34+
* @param fileExtension the file extension of the content, null means not
35+
* provided
36+
* @param content the content
37+
* @return the parsed result
38+
*/
39+
List<ParseResult> parse(String fileExtension, String content);
40+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.github.kbiakov.codeview.highlight.prettify;
2+
3+
import io.github.kbiakov.codeview.highlight.prettify.parser.Job;
4+
import io.github.kbiakov.codeview.highlight.prettify.parser.Prettify;
5+
import io.github.kbiakov.codeview.highlight.parser.ParseResult;
6+
import io.github.kbiakov.codeview.highlight.parser.Parser;
7+
8+
import java.util.ArrayList;
9+
import java.util.Arrays;
10+
import java.util.List;
11+
12+
/**
13+
* The prettify parser for syntax highlight.
14+
* @author Chan Wai Shing <cws1989@gmail.com>
15+
*/
16+
public class PrettifyParser implements Parser {
17+
18+
/**
19+
* The prettify parser.
20+
*/
21+
protected Prettify prettify;
22+
23+
/**
24+
* Constructor.
25+
*/
26+
public PrettifyParser() {
27+
prettify = new Prettify();
28+
}
29+
30+
@Override
31+
public List<ParseResult> parse(String fileExtension, String content) {
32+
Job job = new Job(0, content);
33+
prettify.langHandlerForExtension(fileExtension, content).decorate(job);
34+
List<Object> decorations = job.getDecorations();
35+
36+
37+
List<ParseResult> returnList = new ArrayList<ParseResult>();
38+
39+
// apply style according to the style list
40+
for (int i = 0, iEnd = decorations.size(); i < iEnd; i += 2) {
41+
int endPos = i + 2 < iEnd ? (Integer) decorations.get(i + 2) : content.length();
42+
int startPos = (Integer) decorations.get(i);
43+
returnList.add(new ParseResult(startPos, endPos - startPos, Arrays.asList(new String[]{(String) decorations.get(i + 1)})));
44+
}
45+
46+
return returnList;
47+
}
48+
}

0 commit comments

Comments
 (0)