All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nu.validator.servlet.XhtmlOutlineEmitter Maven / Gradle / Ivy

Go to download

An HTML-checking library (used by https://html5.validator.nu and the HTML5 facet of the W3C Validator)

There is a newer version: 20.7.2
Show newest version
/*
 * Copyright (c) 2012 Vadim Zaslawski, Ontos AG
 * Copyright (c) 2012-2016 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.servlet;

import java.io.IOException;
import java.util.Deque;

import nu.validator.servlet.OutlineBuildingXMLReaderWrapper.Section;
import nu.validator.xml.AttributesImpl;
import nu.validator.xml.XhtmlSaxEmitter;

import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

public class XhtmlOutlineEmitter {

    private static final char[] OUTLINE = "Structural outline".toCharArray();

    private static final char[] A11YOUTLINE = "Screen-reader outline".toCharArray();

    private final Deque
outline; private final XhtmlSaxEmitter emitter; private final AttributesImpl attrs = new AttributesImpl(); public XhtmlOutlineEmitter(final ContentHandler contentHandler, final Deque
outline) { this.emitter = new XhtmlSaxEmitter(contentHandler); this.outline = outline; } public void emit() throws SAXException { if (outline != null) { attrs.clear(); attrs.addAttribute("id", "outline"); emitter.startElement("section", attrs); emitter.startElement("h2"); emitter.characters(OUTLINE); emitter.endElement("h2"); try { emitOutline(outline, 0); } catch (IOException e) { throw new RuntimeException(e); } emitter.endElement("section"); } } boolean hasH1 = false; boolean hasH2 = false; boolean hasH3 = false; boolean hasH4 = false; boolean hasH5 = false; boolean emittedDummyH1 = false; boolean emittedDummyH2 = false; boolean emittedDummyH3 = false; boolean emittedDummyH4 = false; boolean emittedDummyH5 = false; public void emitA11y() throws SAXException { hasH1 = false; hasH2 = false; hasH3 = false; hasH4 = false; hasH5 = false; emittedDummyH1 = false; emittedDummyH2 = false; emittedDummyH3 = false; emittedDummyH4 = false; emittedDummyH5 = false; if (outline != null) { attrs.clear(); attrs.addAttribute("id", "a11youtline"); emitter.startElement("section", attrs); emitter.startElement("h2"); emitter.characters(A11YOUTLINE); emitter.endElement("h2"); try { emitA11yOutline(outline, 0); } catch (IOException e) { throw new RuntimeException(e); } emitter.endElement("section"); } } protected void emitOutline(Deque
outline, int currentDepth) throws IOException, SAXException { emitter.startElement("ol"); for (Section section : outline) { emitter.startElement("li"); StringBuilder headingText = section.getHeadingTextBuilder(); if (headingText.length() > 0) { emitter.startElementWithClass("span", "heading"); emitter.characters(headingText.toString().toCharArray()); emitter.endElement("span"); } else if (section.hasEmptyHeading()) { emitter.characters(("[" + section.getElementName() + " element with empty heading]").toCharArray()); } else if ("h1".equals(section.getElementName()) || "h2".equals(section.getElementName()) || "h3".equals(section.getElementName()) || "h4".equals(section.getElementName()) || "h5".equals(section.getElementName()) || "h6".equals(section.getElementName())) { emitter.characters(("[section implied by empty " + section.getElementName() + " element]").toCharArray()); } else { emitter.characters(("[" + section.getElementName() + " element with no heading]").toCharArray()); } Deque
sections = section.sections; if (!sections.isEmpty()) { emitOutline(sections, currentDepth + 1); } emitter.endElement("li"); } emitter.endElement("ol"); } protected void emitA11yOutline(Deque
outline, int currentDepth) throws IOException, SAXException { for (Section section : outline) { String headingName = section.getHeadingElementName(); if ("h1".equals(headingName)) { hasH1 = true; hasH2 = false; hasH3 = false; hasH4 = false; hasH5 = false; emittedDummyH2 = false; emittedDummyH3 = false; emittedDummyH4 = false; emittedDummyH5 = false; } else if ("h2".equals(headingName)) { hasH2 = true; hasH3 = false; hasH4 = false; hasH5 = false; emittedDummyH3 = false; emittedDummyH4 = false; emittedDummyH5 = false; } else if ("h3".equals(headingName)) { hasH3 = true; hasH4 = false; hasH5 = false; emittedDummyH4 = false; emittedDummyH5 = false; } else if ("h4".equals(headingName)) { hasH4 = true; hasH5 = false; emittedDummyH5 = false; } else if ("h5".equals(headingName)) { hasH5 = true; } if ("h1".equals(headingName) || "h2".equals(headingName) || "h3".equals(headingName) || "h4".equals(headingName) || "h5".equals(headingName) || "h6".equals(headingName)) { StringBuilder headingText = section.getHeadingTextBuilder(); if (!"h1".equals(headingName) && !hasH1 && !emittedDummyH1) { emitMissingHeading("h1"); emittedDummyH1 = true; } if (!"h1".equals(headingName) && !"h2".equals(headingName) && !hasH2 && !emittedDummyH2) { emitMissingHeading("h2"); emittedDummyH2 = true; } if (!"h1".equals(headingName) && !"h2".equals(headingName) && !"h3".equals(headingName) && !hasH3 && !emittedDummyH3) { emitMissingHeading("h3"); emittedDummyH3 = true; } if (!"h1".equals(headingName) && !"h2".equals(headingName) && !"h3".equals(headingName) && !"h4".equals(headingName) && !hasH4 && !emittedDummyH4) { emitMissingHeading("h4"); emittedDummyH4 = true; } if ("h6".equals(headingName) && !hasH5 && !emittedDummyH5) { emitMissingHeading("h5"); emittedDummyH5 = true; } emitter.startElementWithClass("p", headingName); emitter.startElementWithClass("span", "headinglevel"); emitter.characters(("<" + headingName + ">").toCharArray()); emitter.endElement("span"); if (headingText.length() > 0) { emitter.characters( (" " + headingText.toString()).toCharArray()); } else { emitter.startElementWithClass("span", "missingheading"); emitter.characters((" [empty]").toCharArray()); emitter.endElement("span"); } emitter.endElement("p"); } Deque
sections = section.sections; if (!sections.isEmpty()) { emitA11yOutline(sections, currentDepth + 1); } } } private void emitMissingHeading(String headingName) throws SAXException { emitter.startElementWithClass("p", headingName); emitter.startElementWithClass("span", "missingheadinglevel"); emitter.characters(("<" + headingName + ">").toCharArray()); emitter.endElement("span"); emitter.startElementWithClass("span", "missingheading"); emitter.characters((" [missing]").toCharArray()); emitter.endElement("span"); emitter.endElement("p"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy