protected void doTraverseText()

in doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java [295:554]


    protected void doTraverseText(String text, int begin, int end, Sink sink) throws AptParseException {
        boolean anchor = false;
        boolean link = false;
        boolean italic = false;
        boolean bold = false;
        boolean monospaced = false;
        StringBuilder buffer = new StringBuilder(end - begin);

        for (int i = begin; i < end; ++i) {
            char c = text.charAt(i);
            switch (c) {
                case BACKSLASH:
                    if (i + 1 < end) {
                        char escaped = text.charAt(i + 1);
                        switch (escaped) {
                            case SPACE:
                                ++i;
                                flushTraversed(buffer, sink);
                                sink.nonBreakingSpace();
                                break;
                            case '\r':
                            case '\n':
                                ++i;
                                // Skip white space which may follow a line break.
                                while (i + 1 < end && Character.isWhitespace(text.charAt(i + 1))) {
                                    ++i;
                                }
                                flushTraversed(buffer, sink);
                                sink.lineBreak();
                                break;
                            case BACKSLASH:
                            case PIPE:
                            case COMMENT:
                            case EQUAL:
                            case MINUS:
                            case PLUS:
                            case STAR:
                            case LEFT_SQUARE_BRACKET:
                            case RIGHT_SQUARE_BRACKET:
                            case LESS_THAN:
                            case GREATER_THAN:
                            case LEFT_CURLY_BRACKET:
                            case RIGHT_CURLY_BRACKET:
                                ++i;
                                buffer.append(escaped);
                                break;
                            case 'x':
                                if (i + 3 < end && isHexChar(text.charAt(i + 2)) && isHexChar(text.charAt(i + 3))) {
                                    int value = '?';
                                    try {
                                        value = Integer.parseInt(text.substring(i + 2, i + 4), 16);
                                    } catch (NumberFormatException e) {
                                        LOGGER.debug("Not a number: {}", text.substring(i + 2, i + 4));
                                    }

                                    i += 3;
                                    buffer.append((char) value);
                                } else {
                                    buffer.append(BACKSLASH);
                                }
                                break;
                            case 'u':
                                if (i + 5 < end
                                        && isHexChar(text.charAt(i + 2))
                                        && isHexChar(text.charAt(i + 3))
                                        && isHexChar(text.charAt(i + 4))
                                        && isHexChar(text.charAt(i + 5))) {
                                    int value = '?';
                                    try {
                                        value = Integer.parseInt(text.substring(i + 2, i + 6), 16);
                                    } catch (NumberFormatException e) {
                                        LOGGER.debug("Not a number: {}", text.substring(i + 2, i + 6));
                                    }

                                    i += 5;
                                    buffer.append((char) value);
                                } else {
                                    buffer.append(BACKSLASH);
                                }
                                break;
                            default:
                                if (isOctalChar(escaped)) {
                                    int octalChars = 1;
                                    if (isOctalChar(charAt(text, end, i + 2))) {
                                        ++octalChars;
                                        if (isOctalChar(charAt(text, end, i + 3))) {
                                            ++octalChars;
                                        }
                                    }
                                    int value = '?';
                                    try {
                                        value = Integer.parseInt(text.substring(i + 1, i + 1 + octalChars), 8);
                                    } catch (NumberFormatException e) {
                                        LOGGER.debug("Not a number: {}", text.substring(i + 1, i + 1 + octalChars));
                                    }

                                    i += octalChars;
                                    buffer.append((char) value);
                                } else {
                                    buffer.append(BACKSLASH);
                                }
                        }
                    } else {
                        buffer.append(BACKSLASH);
                    }
                    break;

                case LEFT_CURLY_BRACKET: /*}*/
                    if (!anchor && !link) {
                        if (i + 1 < end && text.charAt(i + 1) == LEFT_CURLY_BRACKET /*}*/) {
                            ++i;
                            link = true;
                            flushTraversed(buffer, sink);

                            String linkAnchor = null;

                            if (i + 1 < end && text.charAt(i + 1) == LEFT_CURLY_BRACKET /*}*/) {
                                ++i;
                                StringBuilder buf = new StringBuilder();
                                i = skipTraversedLinkAnchor(text, i + 1, end, buf);
                                linkAnchor = buf.toString();
                            }

                            if (linkAnchor == null) {
                                linkAnchor = getTraversedLink(text, i + 1, end);
                            }

                            if (AptUtils.isInternalLink(linkAnchor)) {
                                linkAnchor = "#" + linkAnchor;
                            }

                            int hashIndex = linkAnchor.indexOf("#");

                            if (hashIndex != -1 && !AptUtils.isExternalLink(linkAnchor)) {
                                String hash = linkAnchor.substring(hashIndex + 1);

                                if (hash.endsWith(".html") && !hash.startsWith("./")) {
                                    LOGGER.debug("Ambiguous link '{}'. If this is a local link, prepend \"./\"!", hash);
                                }

                                // link##anchor means literal
                                if (hash.startsWith("#")) {
                                    linkAnchor = linkAnchor.substring(0, hashIndex) + hash;
                                } else if (!DoxiaUtils.isValidId(hash)) {
                                    linkAnchor = linkAnchor.substring(0, hashIndex) + "#" + DoxiaUtils.encodeId(hash);

                                    LOGGER.debug("Modified invalid link '{}' to '{}'", hash, linkAnchor);
                                }
                            }

                            sink.link(linkAnchor);
                        } else {
                            anchor = true;
                            flushTraversed(buffer, sink);

                            String linkAnchor = getTraversedAnchor(text, i + 1, end);

                            linkAnchor = DoxiaUtils.encodeId(linkAnchor);

                            sink.anchor(linkAnchor);
                        }
                    } else {
                        buffer.append(c);
                    }
                    break;

                case /*{*/ RIGHT_CURLY_BRACKET:
                    if (link && i + 1 < end && text.charAt(i + 1) == /*{*/ RIGHT_CURLY_BRACKET) {
                        ++i;
                        link = false;
                        flushTraversed(buffer, sink);
                        sink.link_();
                    } else if (anchor) {
                        anchor = false;
                        flushTraversed(buffer, sink);
                        sink.anchor_();
                    } else {
                        buffer.append(c);
                    }
                    break;

                case LESS_THAN:
                    if (!italic && !bold && !monospaced) {
                        if (i + 1 < end && text.charAt(i + 1) == LESS_THAN) {
                            if (i + 2 < end && text.charAt(i + 2) == LESS_THAN) {
                                i += 2;
                                monospaced = true;
                                flushTraversed(buffer, sink);
                                sink.monospaced();
                            } else {
                                ++i;
                                bold = true;
                                flushTraversed(buffer, sink);
                                sink.bold();
                            }
                        } else {
                            italic = true;
                            flushTraversed(buffer, sink);
                            sink.italic();
                        }
                    } else {
                        buffer.append(c);
                    }
                    break;

                case GREATER_THAN:
                    if (monospaced
                            && i + 2 < end
                            && text.charAt(i + 1) == GREATER_THAN
                            && text.charAt(i + 2) == GREATER_THAN) {
                        i += 2;
                        monospaced = false;
                        flushTraversed(buffer, sink);
                        sink.monospaced_();
                    } else if (bold && i + 1 < end && text.charAt(i + 1) == GREATER_THAN) {
                        ++i;
                        bold = false;
                        flushTraversed(buffer, sink);
                        sink.bold_();
                    } else if (italic) {
                        italic = false;
                        flushTraversed(buffer, sink);
                        sink.italic_();
                    } else {
                        buffer.append(c);
                    }
                    break;

                default:
                    if (Character.isWhitespace(c)) {
                        buffer.append(SPACE);

                        // Skip to the last char of a sequence of white spaces.
                        while (i + 1 < end && Character.isWhitespace(text.charAt(i + 1))) {
                            ++i;
                        }
                    } else {
                        buffer.append(c);
                    }
            }
        }

        if (monospaced) {
            throw new AptParseException("missing '" + MONOSPACED_END_MARKUP + "'");
        }
        if (bold) {
            throw new AptParseException("missing '" + BOLD_END_MARKUP + "'");
        }
        if (italic) {
            throw new AptParseException("missing '" + ITALIC_END_MARKUP + "'");
        }
        if (link) {
            throw new AptParseException("missing '" + LINK_END_MARKUP + "'");
        }
        if (anchor) {
            throw new AptParseException("missing '" + ANCHOR_END_MARKUP + "'");
        }

        flushTraversed(buffer, sink);
    }