--- /dev/null
+package org.simantics.scl.compiler.markdown.nodes;
+
+import org.simantics.scl.compiler.markdown.inlines.Entities;
+import org.simantics.scl.compiler.markdown.inlines.Subject;
+
+public class Reference {
+ public final String label;
+ public final String url;
+ public final String title;
+
+ public Reference(String label, String url, String title) {
+ this.label = label;
+ this.url = url;
+ this.title = title;
+ }
+
+ public static String normalizeLabel(String label) {
+ StringBuilder b = new StringBuilder();
+ int pos = 0;
+ while(pos < label.length() && Character.isWhitespace(label.charAt(pos)))
+ ++pos;
+ boolean ws = false;
+ while(pos < label.length()) {
+ char c = label.charAt(pos++);
+ if(Character.isWhitespace(c))
+ ws = true;
+ else {
+ if(ws)
+ b.append(' ');
+ b.append(Character.toLowerCase(c));
+ }
+ }
+ return b.toString();
+ }
+
+ public static String cleanUrl(String input) {
+ StringBuilder b = new StringBuilder();
+ int pos = 0;
+ while(pos < input.length()) {
+ char c = input.charAt(pos++);
+ if(c == '\\' && pos < input.length()) {
+ c = input.charAt(pos);
+ if(Subject.getCharType(c) == 2) {
+ b.append(c);
+ ++pos;
+ }
+ else
+ b.append('\\');
+ }
+ else if(c == '&') {
+ int maxPos = Math.min(input.length(), pos+Entities.MAX_ENTITY_LENGTH+1);
+ int p = pos;
+ while(true) {
+ if(p == maxPos) {
+ b.append("&");
+ break;
+ }
+ c = input.charAt(p++);
+ if(c == ';') {
+ String entity = input.substring(pos, p-1);
+ String character = Entities.ENTITY_MAP.get(entity);
+ if(character == null) {
+ b.append("&");
+ break;
+ }
+ else {
+ pos = p;
+ b.append(character);
+ break;
+ }
+ }
+ }
+ }
+ else
+ b.append(c);
+ }
+ return b.toString();
+ }
+
+ public static String cleanTitle(String input) {
+ return cleanUrl(input);
+ }
+}