/*
* Copyright (c) 2007 Mozilla Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package nu.validator.messages;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.Map;
import nu.validator.xml.AttributesImpl;
import nu.validator.xml.XhtmlSaxEmitter;
import org.xml.sax.SAXException;
public final class XhtmlMessageTextHandler implements MessageTextHandler {
private final AttributesImpl attrs = new AttributesImpl();
private static final AttributesImpl LINE_BREAK_ATTRS = new AttributesImpl();
private static final char[] NEWLINE_SUBSTITUTE = { '\u21A9' };
static {
LINE_BREAK_ATTRS.addAttribute("class", "lf");
LINE_BREAK_ATTRS.addAttribute("title", "Line break");
}
private final XhtmlSaxEmitter emitter;
private static final Map<String, String[]> MAGIC_LINKS = new HashMap<>();
static {
MAGIC_LINKS.put("Use CSS instead",
new String[] {"http://wiki.whatwg.org/wiki/Presentational_elements_and_attributes",
"About using CSS instead of presentational elements and attributes."});
MAGIC_LINKS.put("register the names as meta extensions",
new String[] {"http://wiki.whatwg.org/wiki/MetaExtensions",
"About registering names as meta extensions."});
MAGIC_LINKS.put("guidance on providing text alternatives for images",
new String[] {"http://www.w3.org/wiki/HTML/Usage/TextAlternatives",
"About providing text alternatives for images."});
}
/**
* @param emitter
*/
public XhtmlMessageTextHandler(final XhtmlSaxEmitter emitter) {
this.emitter = emitter;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String str = new String(ch);
Map<Integer, String> linkText = new TreeMap<>();
int index;
for (Map.Entry<String, String[]> entry : MAGIC_LINKS.entrySet()) {
index = str.indexOf(entry.getKey());
if (index != -1) {
linkText.put(index,entry.getKey());
}
}
if (!linkText.isEmpty()) {
int position = start;
for (Map.Entry<Integer, String> entry : linkText.entrySet()) {
int linkstart = entry.getKey();
String text = entry.getValue();
emitter.characters(ch, position, linkstart - position - start);
startLink(MAGIC_LINKS.get(text)[0], MAGIC_LINKS.get(text)[1]);
emitter.characters(ch, linkstart, text.length());
endLink();
position = linkstart+text.length();
}
if (position < length) {
characterz(ch, position, length - position);
}
} else {
characterz(ch, start, length);
}
}
private void characterz(char[] ch, int start, int length)
throws SAXException {
int end = start + length;
for (int i = start; i < end; i++) {
char c = ch[i];
switch (c) {
case '\n':
case '\r':
if (start < i) {
emitter.characters(ch, start, i - start);
}
start = i + 1;
emitter.startElement("span", LINE_BREAK_ATTRS);
emitter.characters(NEWLINE_SUBSTITUTE);
emitter.endElement("span");
break;
}
}
if (start < end) {
emitter.characters(ch, start, end - start);
}
}
@Override
public void endCode() throws SAXException {
emitter.endElement("code");
}
@Override
public void endLink() throws SAXException {
emitter.endElement("a");
}
@Override
public void startCode() throws SAXException {
emitter.startElement("code");
}
@Override
public void startLink(String href, String title) throws SAXException {
assert href != null;
attrs.clear();
attrs.addAttribute("href", href);
if (title != null) {
attrs.addAttribute("title", title);
}
emitter.startElement("a", attrs);
}
}