Advertisement
Guest User

Untitled

a guest
Dec 17th, 2017
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.63 KB | None | 0 0
  1. package md2html;
  2.  
  3. import md2html.containers.*;
  4. import md2html.elements.*;
  5.  
  6. import java.io.*;
  7. import java.util.*;
  8. import java.util.regex.*;
  9.  
  10. public class Md2Html {
  11.     private static Stack<Markup> mpElements = new Stack<>(); //стек элементов разметки
  12.     private static Stack<String> charStack = new Stack<>(); //стек символов разметки
  13.     private static StringBuilder s = new StringBuilder(); //строка, в которую будет записываться текст
  14.  
  15.     public static void main(String[] args) throws IOException {
  16.         String inName;
  17.         String outName;
  18.  
  19.         try {
  20.             inName = args[0];
  21.             outName = args[1];
  22.         } catch (ArrayIndexOutOfBoundsException e) {
  23.             System.out.println("File not stated. Usage: Md2Html <in> <out>");
  24.             return;
  25.         }
  26.         BufferedReader in = null;
  27.         PrintWriter out = null;
  28.         try {
  29.             in = new BufferedReader(
  30.                     new InputStreamReader(
  31.                             new FileInputStream(inName), "utf-8"));
  32.             out = new PrintWriter(outName, "utf-8");
  33.  
  34.             Document doc = new Document();
  35.             Markup block = new Paragraph(); //блок - либо абзац, либо заголовок
  36.             Pattern headingPattern = Pattern.compile("#+ .+"); //паттерн заголовка
  37.             boolean isFirstLine = true;
  38.             boolean isNewBlock = true;
  39.             boolean ignoreNewLine = false;
  40.  
  41.             //проходим по файлу
  42.             while (in.ready()) {
  43.                 String currLine = in.readLine();
  44.  
  45.                 // если пропущена строка, то начался либо новый заголовок, либо абзац
  46.                 // обнуляем блок, перед этим записывая его в документ
  47.                 if (currLine.equals("")) {
  48.                     if (isFirstLine) {
  49.                         ignoreNewLine = true;
  50.                     }
  51.                     if (ignoreNewLine) {
  52.                         continue;
  53.                     }
  54.                     ignoreNewLine = true;
  55.                     isNewBlock = true;
  56.                     doc.add(block);
  57.                     block = new Paragraph();
  58.                     continue;
  59.                 }
  60.                 ignoreNewLine = false;
  61.                 isFirstLine = false;
  62.  
  63.                 int i = 0; //указатель символа в строке
  64.                 s = new StringBuilder();
  65.  
  66.                 //определение заголовка
  67.                 Matcher matcher = headingPattern.matcher(currLine);
  68.                 if (matcher.matches() && isNewBlock) {
  69.                     Matcher headingLevelMatcher = Pattern.compile("#+ ").matcher(currLine);
  70.                     headingLevelMatcher.find();
  71.                     int headingLevel = headingLevelMatcher.group().length() - 1;
  72.                     block = new Heading(headingLevel);
  73.                     i += headingLevel + 1; //перемещаем указатель на символ после пробела
  74.                 }
  75.  
  76.                 //если начался новый блок, то он уже не новый (think about it)
  77.                 if (isNewBlock) {
  78.                     mpElements.push(block);
  79.                     isNewBlock = false;
  80.                 }
  81.  
  82.                 // проходим по строке
  83.                 while (i != currLine.length()) {
  84.                     //парсим строку
  85.                     char ch = currLine.charAt(i);
  86.                     boolean isDouble = false; //двойной ли символ разметки
  87.                     boolean isLastChar = (i == currLine.length() - 1); //true если символ последний
  88.                     switch (ch) {
  89.                         case '\\':
  90.                             //если \, то запишем следуюший символ
  91.                             if (!isLastChar) {
  92.                                 i++;
  93.                             }
  94.                             s.append(currLine.charAt(i));
  95.                             break;
  96.                         //символы разметки
  97.                         case '*':
  98.                             if (!isLastChar && currLine.charAt(i + 1) == '*')
  99.                                 isDouble = true;
  100.                             //fall through
  101.                         case '_':
  102.                             if (!isLastChar && currLine.charAt(i + 1) == '_')
  103.                                 isDouble = true;
  104.                             //если окружён пробелами - одиночный символ
  105.                             if ((isLastChar && currLine.charAt(i - 1) == ' ') ||
  106.                                     (i == 0 && currLine.charAt(i + 1) == ' ') ||
  107.                                     (i != 0 && !isLastChar &&
  108.                                             currLine.charAt(i + 1) == ' ' && currLine.charAt(i - 1) == ' ')) {
  109.                                 s.append(ch);
  110.                                 break;
  111.                             }
  112.                             //fall through
  113.                         case '-':
  114.                             //если не "--", то просто добавляем в строку "-"
  115.                             if (ch == '-') {
  116.                                 if (i == currLine.length() - 1 || currLine.charAt(i + 1) != '-') {
  117.                                     s.append(ch);
  118.                                     break;
  119.                                 }
  120.                                 isDouble = true;
  121.                             }
  122.                             //fall through
  123.                         case '+':
  124.                             //если не "++", то просто добавляем в строку "+"
  125.                             if (ch == '+') {
  126.                                 if (i == currLine.length() - 1 || currLine.charAt(i + 1) != '+') {
  127.                                     s.append(ch);
  128.                                     break;
  129.                                 }
  130.                                 isDouble = true;
  131.                             }
  132.                             //fall through
  133.                         case '`':
  134.                             pushMarkup(Character.toString(ch), isDouble);
  135.                             if (isDouble) {
  136.                                 i++;
  137.                             }
  138.                             break;
  139.                         //спецсимволы
  140.                         case '>':
  141.                             s.append("&gt;");
  142.                             break;
  143.                         case '<':
  144.                             s.append("&lt;");
  145.                             break;
  146.                         case '&':
  147.                             s.append("&amp;");
  148.                             break;
  149.                         default:
  150.                             s.append(ch);
  151.                             break;
  152.                     }
  153.                     i++; //переход на следующий символ
  154.                 }
  155.                 mpElements.peek().add(new Text(s.toString().concat("\n"))); //в последний элемент добавляем %s\n
  156.             }
  157.             //игнорирование пустых строк в конце документа
  158.             if (block.size() != 0) {
  159.                 doc.add(block);
  160.             }
  161.             out.print(doc.toMarkup(MarkupType.HTML));
  162.  
  163.         } catch (FileNotFoundException e) {
  164.             System.out.printf("Missing input file: %s\n", e.getMessage());
  165.         } catch (UnsupportedMarkupTypeException e) {
  166.             System.out.printf("Unsupported markup type: %s\n", e.getMarkupType());
  167.         } finally {
  168.             if (in != null) {
  169.                 in.close();
  170.             }
  171.             if (out != null) {
  172.                 out.close();
  173.             }
  174.         }
  175.     }
  176.  
  177.     /**
  178.      * На вход: символ разметки, двойной ли элемент.
  179.      * Возможные варианты символов:
  180.      * Двойные: "--"
  181.      * Возможно двойные: "*", "_"
  182.      * Одиночные: "`"
  183.      * */
  184.     private static void pushMarkup(String mpElem, boolean isDouble) {
  185.         mpElements.peek().add(new Text(s.toString()));
  186.         if (isDouble) {
  187.             mpElem = mpElem.concat(mpElem); //если элемент двойной, то дублировать строку (* -> ** например)
  188.         }
  189.         s = new StringBuilder();
  190.         //если тип разметки равен последнему в стеке
  191.         if (!charStack.isEmpty() && charStack.peek().equals(mpElem)) {
  192.             // [... el1, el2] - добавляем el2 в el1
  193.             Markup t = mpElements.pop();
  194.             mpElements.peek().add(t);
  195.             charStack.pop();
  196.         } else {
  197.             charStack.push(mpElem);
  198.             switch (mpElem) {
  199.                 case "*":
  200.                 case "_":
  201.                     mpElements.push(new Emphasis());
  202.                     break;
  203.                 case "**":
  204.                 case "__":
  205.                     mpElements.push(new Strong());
  206.                     break;
  207.                 case "--":
  208.                     mpElements.push(new Strikeout());
  209.                     break;
  210.                 case "++":
  211.                     mpElements.push(new Underline());
  212.                     break;
  213.                 case "`":
  214.                     mpElements.push(new Code());
  215.                     break;
  216.             }
  217.         }
  218.     }
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement