Search in sources :

Example 1 with BlockParser

use of com.vladsch.flexmark.parser.block.BlockParser in project flexmark-java by vsch.

the class ListItemParser method tryContinue.

@Override
public BlockContinue tryContinue(ParserState state) {
    if (state.isBlank()) {
        // now when we have a Blank line after empty list item, now we need to handle it because the list is not closed and we handle next list item conditions
        Node firstChild = myBlock.getFirstChild();
        myIsEmpty = firstChild == null;
        if (myIsEmpty || firstChild.getNext() == null) {
            myBlock.setHadBlankAfterItemParagraph(true);
        }
        myHadBlankLine = true;
        return BlockContinue.atIndex(state.getNextNonSpaceIndex());
    }
    assert myBlock.getParent() instanceof ListBlock;
    ListBlockParser listBlockParser = (ListBlockParser) state.getActiveBlockParser(myBlock.getParent());
    ParserEmulationProfile emulationProfile = myOptions.getParserEmulationProfile();
    ParserEmulationProfile emulationFamily = emulationProfile.family;
    final int contentIndent = getContentIndent();
    if (emulationFamily == COMMONMARK) {
        // - CommonMark: version 0.27 of the spec, all common mark parsers
        // - Definitions/Defaults:
        // - `ITEM_INDENT` = 4 <!-- not used -->
        // - `CODE_INDENT` = 4
        // - `current indent` = `line indent`
        // - Start List Conditions:
        // - `item indent` < `CODE_INDENT`: new list with new item
        // - `item content indent` >= `CODE_INDENT`: empty item, indented code
        // - Continuation Conditions:
        // - `current indent` >= `list last content indent` + `CODE_INDENT`: indented code
        // - `current indent` >= `list last content indent`: sub-item
        // - `current indent` >= `list indent`: list item
        int currentIndent = state.getIndent();
        int newColumn = state.getColumn() + contentIndent;
        if (currentIndent >= contentIndent + myOptions.getCodeIndent()) {
            // our indented code child
            listBlockParser.setItemHandledLine(state.getLine());
            return continueAtColumn(newColumn);
        } else {
            ListBlockParser.ListData listData = ListBlockParser.parseListMarker(myOptions, myOptions.getCodeIndent(), state);
            if (currentIndent >= contentIndent) {
                if (listData != null) {
                    BlockParser matched = state.getActiveBlockParser();
                    boolean inParagraph = matched.isParagraphParser();
                    boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                    if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                        // just a lazy continuation of us
                        listBlockParser.setItemHandledLineSkipActive(state.getLine());
                        return continueAtColumn(newColumn);
                    } else {
                        // our sub list item
                        listBlockParser.setItemHandledNewListLine(state.getLine());
                        return continueAtColumn(newColumn);
                    }
                } else {
                    if (myIsEmpty) {
                        // our child item, other than a list item, if we are empty then no such thing
                        listBlockParser.setItemHandledLine(state.getLine());
                        return BlockContinue.none();
                    } else {
                        listBlockParser.setItemHandledLine(state.getLine());
                        return continueAtColumn(newColumn);
                    }
                }
            } else if (listData != null) {
                if (!myHadBlankLine && !myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true)) {
                    // our text or lazy continuation
                    listBlockParser.setItemHandledLine(state.getLine());
                    return continueAtColumn(state.getColumn() + currentIndent);
                } else {
                    // here have to see if the item is really a mismatch and we sub-list mismatches
                    boolean overrideSubList = myOptions.isItemTypeMismatchToNewList() && myOptions.isItemTypeMismatchToSubList() && myHadBlankLine;
                    if (!overrideSubList && myOptions.startSubList(listBlockParser.getBlock(), listData.listBlock)) {
                        // we keep it as our sub-item
                        listBlockParser.setItemHandledNewListLine(state.getLine());
                        return continueAtColumn(state.getColumn() + currentIndent);
                    } else {
                        if (myOptions.startNewList(listBlockParser.getBlock(), listData.listBlock)) {
                            // a new list
                            listBlockParser.setItemHandledNewListLine(state.getLine());
                            return BlockContinue.none();
                        } else {
                            // the next line in the list
                            listBlockParser.setItemHandledNewItemLine(state.getLine());
                            return BlockContinue.none();
                        }
                    }
                }
            }
        }
    } else {
        final int itemIndent = myOptions.getItemIndent();
        if (emulationFamily == FIXED_INDENT) {
            // - FixedIndent: Pandoc, MultiMarkdown, Pegdown
            // - Definitions/Defaults:
            // - `ITEM_INDENT` = 4
            // - `CODE_INDENT` = 8
            // - `current indent` = line indent
            // - Start List Conditions:
            // - `current indent` < `ITEM_INDENT`: new list with new item
            // - Continuation Conditions:
            // - `current indent` >= `CODE_INDENT`: item content
            // - `current indent` >= `ITEM_INDENT`: sub-item or content
            // - otherwise: list item or not ours
            int currentIndent = state.getIndent();
            // advance by item indent
            int newColumn = state.getColumn() + itemIndent;
            if (currentIndent >= myOptions.getCodeIndent()) {
                // our indented code child
                listBlockParser.setItemHandledLine(state.getLine());
                return continueAtColumn(newColumn);
            } else {
                ListBlockParser.ListData listData = ListBlockParser.parseListMarker(myOptions, -1, state);
                if (currentIndent >= itemIndent) {
                    if (listData != null) {
                        BlockParser matched = state.getActiveBlockParser();
                        boolean inParagraph = matched.isParagraphParser();
                        boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                        if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                            // just a lazy continuation of us
                            listBlockParser.setItemHandledLineSkipActive(state.getLine());
                            return continueAtColumn(state.getColumn() + currentIndent);
                        } else {
                            // our sub list item
                            listBlockParser.setItemHandledNewListLine(state.getLine());
                            return continueAtColumn(newColumn);
                        }
                    } else {
                        // our child item, other than a list item, if we are empty then no such thing
                        if (myIsEmpty) {
                            listBlockParser.setItemHandledLine(state.getLine());
                            return BlockContinue.none();
                        } else {
                            listBlockParser.setItemHandledLine(state.getLine());
                            return continueAtColumn(newColumn);
                        }
                    }
                } else if (listData != null) {
                    if (!myHadBlankLine && !myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true)) {
                        // our text or lazy continuation
                        listBlockParser.setItemHandledLine(state.getLine());
                        return continueAtColumn(state.getColumn() + currentIndent);
                    } else {
                        // here have to see if the item is really a mismatch and we sub-list mismatches
                        boolean overrideSubList = myOptions.isItemTypeMismatchToNewList() && myOptions.isItemTypeMismatchToSubList() && myHadBlankLine;
                        if (!overrideSubList && myOptions.startSubList(listBlockParser.getBlock(), listData.listBlock)) {
                            // we keep it as our sub-item
                            listBlockParser.setItemHandledNewListLine(state.getLine());
                            return continueAtColumn(state.getColumn() + currentIndent);
                        } else {
                            if (myOptions.startNewList(listBlockParser.getBlock(), listData.listBlock)) {
                                // a new list
                                listBlockParser.setItemHandledNewListLine(state.getLine());
                                return BlockContinue.none();
                            } else {
                                // the next line in the list
                                listBlockParser.setItemHandledNewItemLine(state.getLine());
                                return BlockContinue.none();
                            }
                        }
                    }
                }
            }
        } else {
            final int markerIndent = listBlockParser.getListData().markerIndent;
            final int markerIndex = listBlockParser.getListData().markerIndex;
            if (emulationFamily == KRAMDOWN) {
                // - Kramdown:
                // - Definitions/Defaults:
                // - `ITEM_INDENT` = 4
                // - `CODE_INDENT` = 8
                // - `current indent` = `line indent`
                // - Start List Conditions:
                // - `current indent` < `ITEM_INDENT`: new list with new item
                // - Continuation Conditions:
                // - `current indent` >=  `item content indent`: sub-item or content
                // - `current indent` >= `list indent` + `ITEM_INDENT`
                // - hadBlankLine: end current item, keep loose status, item content
                // - !hadBlankLine: lazy continuation
                // - `current indent` >= `list indent` + `CODE_INDENT`: item content
                // - `current indent` >= `list indent`: list item or not ours
                int currentIndent = state.getIndent();
                int listIndent = markerIndent;
                int newColumn = state.getColumn() + contentIndent;
                ListBlockParser.ListData listData = ListBlockParser.parseListMarker(myOptions, -1, state);
                if (currentIndent >= contentIndent) {
                    // our sub item
                    if (listData != null) {
                        BlockParser matched = state.getActiveBlockParser();
                        boolean inParagraph = matched.isParagraphParser();
                        boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                        if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                            // just a lazy continuation of us
                            listBlockParser.setItemHandledLineSkipActive(state.getLine());
                            return continueAtColumn(newColumn);
                        } else {
                            // our sub list item
                            listBlockParser.setItemHandledNewListLine(state.getLine());
                            return continueAtColumn(newColumn);
                        }
                    } else {
                        // our child item, other than a list item, if we are empty then no such thing
                        if (myIsEmpty) {
                            listBlockParser.setItemHandledLine(state.getLine());
                            return BlockContinue.none();
                        } else {
                            listBlockParser.setItemHandledLine(state.getLine());
                            return continueAtColumn(newColumn);
                        }
                    }
                } else {
                    if (currentIndent >= listIndent + itemIndent) {
                        if (myHadBlankLine) {
                            // indented code, interrupts item but keeps loose status
                            if (myBlock.isHadBlankAfterItemParagraph())
                                myBlock.setLoose(true);
                            listBlockParser.setItemHandledLineSkipActive(state.getLine());
                            return BlockContinue.none();
                        } else {
                            // our text or lazy continuation
                            listBlockParser.setItemHandledLineSkipActive(state.getLine());
                            return continueAtColumn(state.getColumn() + currentIndent);
                        }
                    } else if (listData != null) {
                        if (currentIndent >= listIndent) {
                            // here have to see if the item is really a mismatch and we sub-list mismatches
                            boolean overrideSubList = myOptions.isItemTypeMismatchToNewList() && myOptions.isItemTypeMismatchToSubList() && myHadBlankLine;
                            if (!overrideSubList && myOptions.startSubList(listBlockParser.getBlock(), listData.listBlock)) {
                                // we keep it as our sub-item
                                listBlockParser.setItemHandledNewListLine(state.getLine());
                                return continueAtColumn(state.getColumn() + currentIndent);
                            } else {
                                if (myOptions.startNewList(listBlockParser.getBlock(), listData.listBlock)) {
                                    // a new list
                                    listBlockParser.setItemHandledNewListLine(state.getLine());
                                    return BlockContinue.none();
                                } else {
                                    // the next line in the list
                                    listBlockParser.setItemHandledNewItemLine(state.getLine());
                                    return BlockContinue.none();
                                }
                            }
                        }
                    }
                }
            } else if (emulationProfile == GITHUB_DOC) {
                // - Markdown:
                // - Definitions/Defaults:
                // - `ITEM_INDENT` = 4
                // - `CODE_INDENT` = 8
                // - `current indent` = `line indent`
                // - Start List Conditions:
                // - `current indent` < `ITEM_INDENT`: new list with new item
                // - Continuation Conditions:
                // - `current indent` >= `CODE_INDENT`: item content
                // - `current indent` > `ITEM_INDENT`: sub-item or content
                // - `current indent` > `list indent`: sub-item or content
                // - otherwise: list item or not ours
                int currentIndent = state.getIndent();
                int currentIndex = state.getIndex() + currentIndent;
                int listIndent = markerIndent;
                int listIndex = markerIndent;
                final int contentIndentRemoval = Utils.maxLimit(currentIndent, contentIndent, listIndent + 4);
                if (currentIndent >= myOptions.getCodeIndent()) {
                    // this could be indented code or our lazy continuation
                    listBlockParser.setItemHandledLine(state.getLine());
                    return continueAtColumn(state.getColumn() + Utils.maxLimit(contentIndent, itemIndent));
                } else {
                    ListBlockParser.ListData listData = ListBlockParser.parseListMarker(myOptions, -1, state);
                    if (currentIndent > itemIndent) {
                        if (listData != null) {
                            // our sub item
                            BlockParser matched = state.getActiveBlockParser();
                            boolean inParagraph = matched.isParagraphParser();
                            boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                            if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                                // just a lazy continuation of us
                                listBlockParser.setItemHandledLineSkipActive(state.getLine());
                                return continueAtColumn(state.getColumn() + currentIndent);
                            } else {
                                // our sub list item
                                listBlockParser.setItemHandledNewListLine(state.getLine());
                                return continueAtColumn(state.getColumn() + contentIndentRemoval);
                            }
                        } else {
                            // our content
                            listBlockParser.setItemHandledLine(state.getLine());
                            return continueAtColumn(state.getColumn() + itemIndent);
                        }
                    } else {
                        if (currentIndent > listIndent) {
                            if (listData != null) {
                                // our sublist
                                BlockParser matched = state.getActiveBlockParser();
                                boolean inParagraph = matched.isParagraphParser();
                                boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                                if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                                    // just a lazy continuation of us
                                    listBlockParser.setItemHandledLineSkipActive(state.getLine());
                                    return continueAtColumn(state.getColumn() + currentIndent);
                                } else {
                                    // our sub list item
                                    listBlockParser.setItemHandledNewListLine(state.getLine());
                                    return continueAtColumn(state.getColumn() + contentIndentRemoval);
                                }
                            } else {
                                // our content
                                listBlockParser.setItemHandledLine(state.getLine());
                                return continueAtColumn(state.getColumn() + contentIndentRemoval);
                            }
                        } else {
                            if (listData != null) {
                                // here have to see if the item is really a mismatch and we sub-list mismatches
                                // the next line in the list
                                boolean overrideSubList = myOptions.isItemTypeMismatchToNewList() && myOptions.isItemTypeMismatchToSubList() && myHadBlankLine;
                                if (!overrideSubList && myOptions.startSubList(listBlockParser.getBlock(), listData.listBlock)) {
                                    // we keep it as our sub-item
                                    listBlockParser.setItemHandledNewListLine(state.getLine());
                                    return continueAtColumn(state.getColumn() + contentIndentRemoval);
                                } else {
                                    if (myOptions.startNewList(listBlockParser.getBlock(), listData.listBlock)) {
                                        // a new list
                                        listBlockParser.setItemHandledNewListLine(state.getLine());
                                        return BlockContinue.none();
                                    } else {
                                        BlockParser matched = state.getActiveBlockParser();
                                        boolean inParagraph = matched.isParagraphParser();
                                        boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                                        if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                                            // just a lazy continuation of us
                                            listBlockParser.setItemHandledLineSkipActive(state.getLine());
                                            return continueAtColumn(state.getColumn() + currentIndent);
                                        } else {
                                            // the next line in the list
                                            listBlockParser.setItemHandledNewItemLine(state.getLine());
                                            return BlockContinue.none();
                                        }
                                    }
                                }
                            } else if (!myHadBlankLine || state.getActiveBlockParser() instanceof FencedCodeBlockParser) {
                                // our lazy continuation or a new element
                                // Issue #66, if fenced code follows then need to interrupt the list
                                listBlockParser.setItemHandledLine(state.getLine());
                                return continueAtColumn(state.getColumn() + currentIndent);
                            }
                        }
                    }
                }
            } else if (emulationFamily == MARKDOWN) {
                // - Markdown:
                // - Definitions/Defaults:
                // - `ITEM_INDENT` = 4
                // - `CODE_INDENT` = 8
                // - `current indent` = `line indent`
                // - Start List Conditions:
                // - `current indent` < `ITEM_INDENT`: new list with new item
                // - Continuation Conditions:
                // - `current indent` >= `CODE_INDENT`: item content
                // - `current indent` > `ITEM_INDENT`: sub-item or content
                // - `current indent` > `list indent`: sub-item or content
                // - otherwise: list item or not ours
                int currentIndent = state.getIndent();
                if (currentIndent >= myOptions.getCodeIndent()) {
                    // this could be indented code or our lazy continuation
                    listBlockParser.setItemHandledLine(state.getLine());
                    return continueAtColumn(state.getColumn() + itemIndent);
                } else {
                    ListBlockParser.ListData listData = ListBlockParser.parseListMarker(myOptions, -1, state);
                    if (currentIndent > itemIndent) {
                        if (listData != null) {
                            // our sub item
                            BlockParser matched = state.getActiveBlockParser();
                            boolean inParagraph = matched.isParagraphParser();
                            boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                            if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                                // just a lazy continuation of us
                                listBlockParser.setItemHandledLineSkipActive(state.getLine());
                                return continueAtColumn(state.getColumn() + currentIndent);
                            } else {
                                // our sub list item
                                listBlockParser.setItemHandledNewListLine(state.getLine());
                                return continueAtColumn(state.getColumn() + itemIndent);
                            }
                        } else {
                            // our content
                            listBlockParser.setItemHandledLine(state.getLine());
                            return continueAtColumn(state.getColumn() + itemIndent);
                        }
                    } else {
                        int listIndent = markerIndent;
                        if (currentIndent > listIndent) {
                            if (listData != null) {
                                // our sublist
                                BlockParser matched = state.getActiveBlockParser();
                                boolean inParagraph = matched.isParagraphParser();
                                boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                                if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                                    // just a lazy continuation of us
                                    listBlockParser.setItemHandledLineSkipActive(state.getLine());
                                    return continueAtColumn(state.getColumn() + currentIndent);
                                } else {
                                    // our sub list item
                                    listBlockParser.setItemHandledNewListLine(state.getLine());
                                    return continueAtColumn(state.getColumn() + currentIndent);
                                }
                            } else {
                                // our content
                                listBlockParser.setItemHandledLine(state.getLine());
                                return continueAtColumn(state.getColumn() + currentIndent);
                            }
                        } else if (listData != null) {
                            // here have to see if the item is really a mismatch and we sub-list mismatches
                            // the next line in the list
                            boolean overrideSubList = myOptions.isItemTypeMismatchToNewList() && myOptions.isItemTypeMismatchToSubList() && myHadBlankLine;
                            if (!overrideSubList && myOptions.startSubList(listBlockParser.getBlock(), listData.listBlock)) {
                                // we keep it as our sub-item
                                listBlockParser.setItemHandledNewListLine(state.getLine());
                                return continueAtColumn(state.getColumn() + currentIndent);
                            } else {
                                if (myOptions.startNewList(listBlockParser.getBlock(), listData.listBlock)) {
                                    // a new list
                                    listBlockParser.setItemHandledNewListLine(state.getLine());
                                    return BlockContinue.none();
                                } else {
                                    BlockParser matched = state.getActiveBlockParser();
                                    boolean inParagraph = matched.isParagraphParser();
                                    boolean inParagraphListItem = inParagraph && matched.getBlock().getParent() instanceof ListItem && matched.getBlock() == matched.getBlock().getParent().getFirstChild();
                                    if (inParagraphListItem && (!myOptions.canInterrupt(listData.listBlock, listData.isEmpty, true) || !myOptions.canStartSubList(listData.listBlock, listData.isEmpty))) {
                                        // just a lazy continuation of us
                                        listBlockParser.setItemHandledLineSkipActive(state.getLine());
                                        return continueAtColumn(state.getColumn() + currentIndent);
                                    } else {
                                        // the next line in the list
                                        listBlockParser.setItemHandledNewItemLine(state.getLine());
                                        return BlockContinue.none();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return BlockContinue.none();
}
Also used : ParserEmulationProfile(com.vladsch.flexmark.parser.ParserEmulationProfile) BlockParser(com.vladsch.flexmark.parser.block.BlockParser) AbstractBlockParser(com.vladsch.flexmark.parser.block.AbstractBlockParser)

Example 2 with BlockParser

use of com.vladsch.flexmark.parser.block.BlockParser in project zeppelin by apache.

the class UMLBlockQuoteParser method tryContinue.

@Override
public BlockContinue tryContinue(ParserState state) {
    if (hadClose) {
        return BlockContinue.none();
    }
    final int index = state.getIndex();
    BasedSequence line = state.getLineWithEOL();
    final Matcher matcher = YUML_BLOCK_END.matcher(line.subSequence(index));
    if (!matcher.matches()) {
        return BlockContinue.atIndex(index);
    } else {
        // if have open gitlab block quote last child then let them handle it
        Node lastChild = block.getLastChild();
        if (lastChild instanceof UMLBlockQuote) {
            final BlockParser parser = state.getActiveBlockParser((Block) lastChild);
            if (parser instanceof UMLBlockQuoteParser && !((UMLBlockQuoteParser) parser).hadClose) {
                // let the child handle it
                return BlockContinue.atIndex(index);
            }
        }
        hadClose = true;
        block.setClosingMarker(state.getLine().subSequence(index, index + 3));
        block.setClosingTrailing(state.getLineWithEOL().subSequence(matcher.start(1), matcher.end(1)));
        return BlockContinue.atIndex(state.getLineEndIndex());
    }
}
Also used : BlockParser(com.vladsch.flexmark.parser.block.BlockParser) AbstractBlockParser(com.vladsch.flexmark.parser.block.AbstractBlockParser) MatchedBlockParser(com.vladsch.flexmark.parser.block.MatchedBlockParser) Matcher(java.util.regex.Matcher) BasedSequence(com.vladsch.flexmark.util.sequence.BasedSequence) Node(com.vladsch.flexmark.util.ast.Node)

Aggregations

AbstractBlockParser (com.vladsch.flexmark.parser.block.AbstractBlockParser)2 BlockParser (com.vladsch.flexmark.parser.block.BlockParser)2 ParserEmulationProfile (com.vladsch.flexmark.parser.ParserEmulationProfile)1 MatchedBlockParser (com.vladsch.flexmark.parser.block.MatchedBlockParser)1 Node (com.vladsch.flexmark.util.ast.Node)1 BasedSequence (com.vladsch.flexmark.util.sequence.BasedSequence)1 Matcher (java.util.regex.Matcher)1