package com.orgzly.android.util; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.URLSpan; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * */ public class NoteContentParser { private final static String LINK_SCHEMES = "https?|mailto|tel|voicemail|geo|sms|smsto|mms|mmsto"; private final static String PLAIN_LINK = "((" + LINK_SCHEMES + "):\\S+)"; /* Same as the above, but ] ends the link too. */ private final static String BRACKET_LINK = "((" + LINK_SCHEMES + "):[^]\\s]+)"; /* Allows anything as a link. Probably needs some constraints. * See http://orgmode.org/manual/External-links.html and org-any-link-re */ private final static String BRACKET_ANY_LINK = "(([^]]+))"; public static SpannableStringBuilder fromOrg(String s) { SpannableStringBuilder ssb = new SpannableStringBuilder(s); doOrgLinksWithName(ssb, BRACKET_LINK, true); doOrgLinksWithName(ssb, BRACKET_ANY_LINK, false); doOrgLinks(ssb, BRACKET_LINK, true); doPlainLinks(ssb, PLAIN_LINK, true); return ssb; } /** * [[http://link.com][Link]] */ private static void doOrgLinksWithName(SpannableStringBuilder ssb, String linkRegex, boolean createLinks) { Pattern p = Pattern.compile("\\[\\[" + linkRegex + "\\]\\[([^]]+)\\]\\]"); Matcher m = p.matcher(ssb); while (m.find()) { String link = m.group(1); String name = m.group(3); ssb.replace(m.start(), m.end(), name); if (createLinks) { setUrlSpan(ssb, link, m.start(), m.start() + name.length()); } /* Must re-create Matcher, as ssb size is modified. */ m = p.matcher(ssb); } } /** * [[http://link.com]] */ private static void doOrgLinks(SpannableStringBuilder ssb, String linkRegex, boolean createLinks) { Pattern p = Pattern.compile("\\[\\[" + linkRegex + "\\]\\]"); Matcher m = p.matcher(ssb); while (m.find()) { String link = m.group(1); ssb.replace(m.start(), m.end(), link); if (createLinks) { setUrlSpan(ssb, link, m.start(), m.start() + link.length()); } /* Must re-create Matcher, as ssb size is modified. */ m = p.matcher(ssb); } } /** * http://link.com */ private static void doPlainLinks(SpannableStringBuilder ssb, String linkRegex, boolean createLinks) { if (!createLinks) { return; } Pattern p = Pattern.compile(linkRegex); Matcher m = p.matcher(ssb); while (m.find()) { String link = m.group(1); /* Only if the first character has no URLSpan. */ if (ssb.getSpans(m.start(), m.start() + 1, URLSpan.class).length == 0) { setUrlSpan(ssb, link, m.start(), m.end()); } } } private static void setUrlSpan(SpannableStringBuilder ssb, String link, int start, int end) { ssb.setSpan(new URLSpan(link), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } }