update
All checks were successful
Markup Tests / test (push) Successful in 8s
Markdown to Html Tests / test (push) Successful in 17s

This commit is contained in:
2026-02-17 09:32:08 +03:00
commit 2f05f238e9
109 changed files with 9369 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public abstract class AbstractList implements ContainsInListItem {
private final List<ListItem> items;
private final String highlight;
private final String texBegin;
private final String texEnd;
protected AbstractList(
List<ListItem> items,
String highlight,
String texBegin,
String texEnd
) {
this.items = items;
this.highlight = highlight;
this.texBegin = texBegin;
this.texEnd = texEnd;
}
@Override
public void toHtml(StringBuilder sb) {
sb.append("<").append(highlight).append(">");
for (ListItem item : items) {
item.toHtml(sb);
}
sb.append("</").append(highlight).append(">");
}
@Override
public void toMarkdown(StringBuilder sb) {}
@Override
public void toTex(StringBuilder sb) {
sb.append(texBegin);
for (ListItem item : items) {
item.toTex(sb);
}
sb.append(texEnd);
}
}

View File

@@ -0,0 +1,66 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public abstract class AbstractMarkup implements Markdown, Html, Tex {
protected final List<? extends Markup> items;
private final String highlightMarkdown;
private final String highlightHtml;
private final String highlightTexOpen;
private final String highlightTexClose;
protected AbstractMarkup(
List<? extends Markup> items,
String highlightMarkdown,
String highlightHtml,
String highlightTexOpen,
String highlightTexClose
) {
this.items = items;
this.highlightMarkdown = highlightMarkdown;
this.highlightHtml = highlightHtml;
this.highlightTexOpen = highlightTexOpen;
this.highlightTexClose = highlightTexClose;
}
@Override
public void toMarkdown(StringBuilder sb) {
sb.append(highlightMarkdown);
for (Markup item : items) {
item.toMarkdown(sb);
}
sb.append(highlightMarkdown);
}
@Override
public void toHtml(StringBuilder sb) {
if (!highlightHtml.isEmpty()) {
sb.append("<").append(highlightHtml).append(">");
}
for (Markup item : items) {
item.toHtml(sb);
}
if (!highlightHtml.isEmpty()) {
sb.append("</").append(highlightHtml).append(">");
}
}
@Override
public void toTex(StringBuilder sb) {
sb.append(highlightTexOpen);
for (Markup item : items) {
if (item instanceof Text) {
((Text) item).toTex(sb);
} else if (item instanceof AbstractMarkup) {
((AbstractMarkup) item).toTex(sb);
} else if (item instanceof AbstractList) {
((AbstractList) item).toTex(sb);
}
}
sb.append(highlightTexClose);
}
}

View File

@@ -0,0 +1,6 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public interface ContainsInListItem extends Markup {}

13
java/markup/Emphasis.java Normal file
View File

@@ -0,0 +1,13 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class Emphasis extends AbstractMarkup implements PartOfParagraph {
public Emphasis(List<PartOfParagraph> items) {
super(items, "*", "em", "\\emph{", "}");
}
}

8
java/markup/Html.java Normal file
View File

@@ -0,0 +1,8 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public interface Html {
void toHtml(StringBuilder sb);
}

13
java/markup/ListItem.java Normal file
View File

@@ -0,0 +1,13 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class ListItem extends AbstractMarkup implements Markup {
public ListItem(List<ContainsInListItem> items) {
super(items, "", "li", "\\item ", "");
}
}

View File

@@ -0,0 +1,8 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public interface Markdown {
void toMarkdown(StringBuilder sb);
}

6
java/markup/Markup.java Normal file
View File

@@ -0,0 +1,6 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public interface Markup extends Markdown, Html, Tex {}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,71 @@
package markup;
import base.Asserts;
import base.BaseChecker;
import base.TestCounter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
*/
public final class MarkupTester {
private final Map<String, String> mapping;
private final String toString;
private MarkupTester(final Map<String, String> mapping, final String toString) {
this.mapping = mapping;
this.toString = toString;
}
public static Consumer<TestCounter> variant(final Consumer<Checker> checker, final String name, final Map<String, String> mapping) {
return counter -> test(checker).accept(new MarkupTester(mapping, "to" + name), counter);
}
public static BiConsumer<MarkupTester, TestCounter> test(final Consumer<Checker> tester) {
return (checker, counter) -> tester.accept(checker.new Checker(counter));
}
@Override
public String toString() {
return toString;
}
public class Checker extends BaseChecker {
public Checker(final TestCounter counter) {
super(counter);
}
private <T> MethodHandle findMethod(final T value) {
try {
return MethodHandles.publicLookup().findVirtual(value.getClass(), toString, MethodType.methodType(void.class, StringBuilder.class));
} catch (final NoSuchMethodException | IllegalAccessException e) {
throw Asserts.error("Cannot find method 'void %s(StringBuilder)' for %s", toString, value.getClass());
}
}
public <T> void test(final T value, String expectedTemplate) {
final MethodHandle method = findMethod(value);
for (final Map.Entry<String, String> entry : mapping.entrySet()) {
expectedTemplate = expectedTemplate.replace(entry.getKey(), entry.getValue());
}
final String expected = expectedTemplate;
counter.println("Test " + counter.getTestNo());
counter.test(() -> {
final StringBuilder sb = new StringBuilder();
try {
method.invoke(value, sb);
} catch (final Throwable e) {
throw Asserts.error("%s(StringBuilder) for %s thrown exception: %s", toString, value.getClass(), e);
}
Asserts.assertEquals("Result", expected, sb.toString());
});
}
}
}

View File

@@ -0,0 +1,13 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class OrderedList extends AbstractList {
public OrderedList(List<ListItem> items) {
super(items, "ol", "\\begin{enumerate}", "\\end{enumerate}");
}
}

View File

@@ -0,0 +1,16 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class Paragraph
extends AbstractMarkup
implements ContainsInListItem, PrimePart
{
public Paragraph(List<PartOfParagraph> items) {
super(items, "", "p", "\\par{}", "");
}
}

View File

@@ -0,0 +1,6 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public interface PartOfParagraph extends Markup {}

View File

@@ -0,0 +1,6 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public interface PrimePart extends Markup {}

View File

@@ -0,0 +1,13 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class Strikeout extends AbstractMarkup implements PartOfParagraph {
public Strikeout(List<PartOfParagraph> items) {
super(items, "~", "s", "\\textst{", "}");
}
}

13
java/markup/Strong.java Normal file
View File

@@ -0,0 +1,13 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class Strong extends AbstractMarkup implements PartOfParagraph {
public Strong(List<PartOfParagraph> items) {
super(items, "__", "strong", "\\textbf{", "}");
}
}

8
java/markup/Tex.java Normal file
View File

@@ -0,0 +1,8 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public interface Tex {
void toTex(StringBuilder sb);
}

27
java/markup/Text.java Normal file
View File

@@ -0,0 +1,27 @@
package markup;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class Text implements PartOfParagraph {
private final String text;
public Text(String text) {
this.text = text;
}
@Override
public void toHtml(StringBuilder sb) {
sb.append(text);
}
@Override
public void toMarkdown(StringBuilder sb) {
sb.append(text);
}
public void toTex(StringBuilder sb) {
sb.append(text);
}
}

View File

@@ -0,0 +1,13 @@
package markup;
import java.util.List;
/**
* @author Nikita Doschennikov (me@fymio.us)
*/
public class UnorderedList extends AbstractList {
public UnorderedList(List<ListItem> items) {
super(items, "ul", "\\begin{itemize}", "\\end{itemize}");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 88 KiB

View File

@@ -0,0 +1,157 @@
classDiagram
%% Интерфейсы
class Markdown {
<<interface>>
+toMarkdown(StringBuilder)
}
class Html {
<<interface>>
+toHtml(StringBuilder)
}
class Markup {
<<interface>>
+toMarkdown(StringBuilder)
+toHtml(StringBuilder)
}
class PartOfParagraph {
<<interface>>
+toMarkdown(StringBuilder)
+toHtml(StringBuilder)
}
class ContainsInListItem {
<<interface>>
+toMarkdown(StringBuilder)
+toHtml(StringBuilder)
}
class PrimePart {
<<interface>>
+toMarkdown(StringBuilder)
+toHtml(StringBuilder)
}
%% Наследование интерфейсов
Markup --|> Markdown
Markup --|> Html
PartOfParagraph --|> Markup
ContainsInListItem --|> Markup
PrimePart --|> Markup
%% Абстрактные классы
class AbstractMarkup {
<<abstract>>
#List~Markup~ items
-String highlightMarkdown
-String highlightHtml
-String highlightTexOpen
-String highlightTexClose
+AbstractMarkup(List, String, String, String, String)
+toMarkdown(StringBuilder)
+toHtml(StringBuilder)
+toTex(StringBuilder)
}
class AbstractList {
<<abstract>>
-List~ListItem~ items
-String highlight
-String texBegin
-String texEnd
+AbstractList(List, String, String, String)
+toHtml(StringBuilder)
+toMarkdown(StringBuilder)
+toTex(StringBuilder)
}
%% Абстрактные классы реализуют интерфейсы
AbstractMarkup ..|> Markdown
AbstractMarkup ..|> Html
AbstractList ..|> ContainsInListItem
%% Inline элементы
class Text {
-String text
+Text(String)
+toMarkdown(StringBuilder)
+toHtml(StringBuilder)
+toTex(StringBuilder)
}
class Emphasis {
+Emphasis(List~PartOfParagraph~)
}
class Strong {
+Strong(List~PartOfParagraph~)
}
class Strikeout {
+Strikeout(List~PartOfParagraph~)
}
%% Inline элементы наследуются и реализуют
Text ..|> PartOfParagraph
Emphasis --|> AbstractMarkup
Emphasis ..|> PartOfParagraph
Strong --|> AbstractMarkup
Strong ..|> PartOfParagraph
Strikeout --|> AbstractMarkup
Strikeout ..|> PartOfParagraph
%% Paragraph
class Paragraph {
+Paragraph(List~PartOfParagraph~)
}
Paragraph --|> AbstractMarkup
Paragraph ..|> ContainsInListItem
Paragraph ..|> PrimePart
%% Списки
class OrderedList {
+OrderedList(List~ListItem~)
}
class UnorderedList {
+UnorderedList(List~ListItem~)
}
class ListItem {
+ListItem(List~ContainsInListItem~)
}
OrderedList --|> AbstractList
UnorderedList --|> AbstractList
ListItem --|> AbstractMarkup
ListItem ..|> Markup
%% Зависимости (что может содержать что)
AbstractMarkup o-- Markup : contains
AbstractList o-- ListItem : contains
Emphasis o-- PartOfParagraph : contains
Strong o-- PartOfParagraph : contains
Strikeout o-- PartOfParagraph : contains
Paragraph o-- PartOfParagraph : contains
ListItem o-- ContainsInListItem : contains
%% Стили
style Markdown fill:#e1f5ff
style Html fill:#e1f5ff
style Markup fill:#e1f5ff
style PartOfParagraph fill:#fff4e1
style ContainsInListItem fill:#fff4e1
style PrimePart fill:#fff4e1
style AbstractMarkup fill:#ffe1f5
style AbstractList fill:#ffe1f5
style Text fill:#e1ffe1
style Emphasis fill:#e1ffe1
style Strong fill:#e1ffe1
style Strikeout fill:#e1ffe1
style Paragraph fill:#ffe1e1
style OrderedList fill:#f5e1ff
style UnorderedList fill:#f5e1ff
style ListItem fill:#f5e1ff

View File

@@ -0,0 +1,7 @@
/**
* Tests for <a href="https://www.kgeorgiy.info/courses/prog-intro/homeworks.html#markup">Markup</a> homework
* of <a href="https://www.kgeorgiy.info/courses/prog-intro/">Introduction to Programming</a> course.
*
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
*/
package markup;