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

net.thevpc.commons.md.docusaurus.DocusaurusMdParser Maven / Gradle / Ivy

The newest version!
package net.thevpc.commons.md.docusaurus;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

import net.thevpc.commons.md.*;
import net.thevpc.commons.md.*;

public class DocusaurusMdParser implements MdParser {

    private BufferedReader reader;

    List buffer = new ArrayList<>();

    public DocusaurusMdParser(Reader r) {
        this.reader = (r instanceof BufferedReader) ? (BufferedReader) r : new BufferedReader(r);
    }

    private String nextLine() {
        if (this.buffer.isEmpty())
      try {
            return this.reader.readLine();
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
        return this.buffer.remove(this.buffer.size() - 1);
    }

    private void pushBack(String line) {
        this.buffer.add(line);
    }

    private MdElement parseNextLine(Predicate stopPredicate) {
        String line = nextLine();
        if (line == null) {
            return null;
        }
        if (stopPredicate != null && stopPredicate.test(line)) {
            pushBack(line);
            return null;
        }
        if (line.startsWith("---") && line.trim().equals("---")) {
            return (MdElement) new MdLineSeparator("---", line.substring(3));
        }
        if (line.startsWith(mul('\t', 5) + "-")) {
            return (MdElement) MdFactory.ul(6, new DocusaurusInlineParser(line.substring(6).trim()).parse());
        }
        if (line.startsWith("\t-")) {
            return (MdElement) MdFactory.ul(1, new DocusaurusInlineParser(line.substring(1).trim()).parse());
        }
        for (int i = 6; i > 0; i--) {
            String id = mul('#', i);
            if (line.startsWith(id)) {
                return (MdElement) new MdTitle(id, line.substring(i).trim(), i);
            }
            id = mul('*', i);
            if (line.startsWith(id)) {
                return (MdElement) new MdTitle(id, line.substring(i).trim(), i);
            }
            id = mul('+', i);
            if (line.startsWith(id)) {
                return (MdElement) MdFactory.ul(i, new DocusaurusInlineParser(line.substring(i).trim()).parse());
            }
            id = mul('-', i);
            if (line.startsWith(id)) {
                return (MdElement) MdFactory.ul(i, new DocusaurusInlineParser(line.substring(i).trim()).parse());
            }
            if (i > 1) {
                id = mul('\t', i - 1) + "-";
                if (line.startsWith(id)) {
                    return (MdElement) MdFactory.ul(i, new DocusaurusInlineParser(line.substring(6).trim()).parse());
                }
            }
        }
        if (line.matches("[0-9]+[.] .*")) {
            int x = line.indexOf('.');
            return (MdElement) MdFactory.ol(Integer.parseInt(line.substring(0, x)), 1, new DocusaurusInlineParser(line.substring(x + 1)).parse());
        }
        if (line.startsWith("```")) {
            String id = line.substring(3).trim();
            if (!id.contains("```")) {
                StringBuilder code = new StringBuilder();
                boolean first = true;
                while ((line = nextLine()) != null) {
                    if (first) {
                        first = false;
                    } else {
                        code.append("\n");
                    }
                    if (line.startsWith("```")) {
                        break;
                    }
                    code.append(line);
                }
                return (MdElement) new MdCode(id, code.toString(), false);
            }
        }
        if (line.startsWith(":::")) {
            String type = line.substring(3).trim();
            MdElement t = parse(x -> x.startsWith(":::"));
            String threeDots = nextLine();
            if (!threeDots.trim().equals(":::")) {
                System.err.println("Expected :::");
                pushBack(threeDots);
            }
            return (MdElement) new MdAdmonition(type, MdAdmonitionType.valueOf(type.toUpperCase()), t);
        }
        if (line.startsWith("|") && line.endsWith("|") && line.length() > 1) {
            pushBack(line);
            return readTable();
        }
        if (line.matches("[<][a-zA-Z-]+( .*)?")) {
            pushBack(line);
            return readXml();
        }
        return new DocusaurusInlineParser(line).parse();
    }

    public MdElement parse() {
        return parse(null);
    }

    private MdElement parse(Predicate stopPredicate) {
        List all = new ArrayList<>();
        while (true) {
            MdElement pl = parseNextLine(stopPredicate);
            if (pl == null) {
                break;
            }
            all.add(pl);
        }
        if (all.isEmpty()) {
            return null;
        }
        if (all.size() == 1) {
            return all.get(0);
        }
        return (MdElement) new MdSequence("", all.toArray(new MdElement[0]), false);
    }

    private static String mul(char s, int count) {
        char[] cc = new char[count];
        Arrays.fill(cc, s);
        return new String(cc);
    }

    private MdElement readXml() {
        String line = nextLine();
        if (line.matches("[<][a-zA-Z-]+( .*)?")) {
            int s = line.indexOf(' ');
            if (s < 0) {
                s = line.indexOf('\t');
            }
            String tagName = (s < 0) ? line.substring(1) : line.substring(1, s);
            StringBuilder startTag = new StringBuilder();
            startTag.append(line);
            if (!line.endsWith(">")) {
                do {
                    line = nextLine();
                    if (line == null) {
                        System.err.println("invalid xml tag");
                        break;
                    }
                    startTag.append("\n");
                    startTag.append(line);
                } while (!line.endsWith(">"));
            }
            MdElement t = parse(x -> x.startsWith(""));
            nextLine();
            return (MdElement) new MdXml(tagName, startTag.substring(1 + tagName.length() + 1, startTag.length() - 1), t);
        }
        return null;
    }

    private MdElement readTable() {
        MdRow headers = readRow();
        MdRow sorts = readRow();
        List columns = new ArrayList<>();
        for (int i = 0; i < headers.size(); i++) {
            String t = sorts.get(i).asText().getText().trim();
            MdHorizontalAlign ha
                    = t.matches(":[-]+:") ? MdHorizontalAlign.CENTER
                    : t.matches("[-]+:") ? MdHorizontalAlign.RIGHT
                    : MdHorizontalAlign.LEFT;
            columns.add(new MdColumn(headers.get(i), ha));
        }
        List rows = new ArrayList<>();
        while (true) {
            MdRow t = readRow();
            if (t == null) {
                break;
            }
            rows.add(t);
        }
        return (MdElement) new MdTable(columns.toArray(new MdColumn[0]), rows.toArray(new MdRow[0]));
    }

    private MdRow readRow() {
        String line = nextLine();
        if (line != null) {
            line = line.trim();
            if (line.isEmpty()) {
                return null;
            }
            MdElement e = new DocusaurusInlineParser(line).parse();
            if (e == null) {
                return null;
            }
            MdSequence seq = (e instanceof MdSequence) ? ((MdSequence) e) : new MdSequence("", new MdElement[]{e}, true);

            List cells = new ArrayList<>();
            List currentCol = new ArrayList<>();
            boolean firstItem = true;
            for (MdElement elem : new ArrayList(Arrays.asList(seq.getElements()))) {
                if (elem.isText() && elem.asText().getText().equals("|")) {
                    if (!firstItem || !currentCol.isEmpty()) {
                        if (currentCol.isEmpty()) {
                            currentCol.add(new MdText(" "));
                        }
                        cells.add(MdFactory.seqInline(currentCol));
                        currentCol.clear();
                    }
                } else {
                    currentCol.add(elem);
                }
                if (firstItem) {
                    firstItem = false;
                }
            }
            if (!currentCol.isEmpty()) {
                cells.add(MdFactory.seqInline(currentCol));
            }
            return new MdRow(cells.toArray(new MdElement[0]), false);
        }
        return null;
    }

    @Override
    public void close() {
        try {
            reader.close();
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy