diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 1ff0c42..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,63 +0,0 @@
-###############################################################################
-# Set default behavior to automatically normalize line endings.
-###############################################################################
-* text=auto
-
-###############################################################################
-# Set default behavior for command prompt diff.
-#
-# This is need for earlier builds of msysgit that does not have it on by
-# default for csharp files.
-# Note: This is only used by command line
-###############################################################################
-#*.cs diff=csharp
-
-###############################################################################
-# Set the merge driver for project and solution files
-#
-# Merging from the command prompt will add diff markers to the files if there
-# are conflicts (Merging from VS is not affected by the settings below, in VS
-# the diff markers are never inserted). Diff markers may cause the following
-# file extensions to fail to load in VS. An alternative would be to treat
-# these files as binary and thus will always conflict and require user
-# intervention with every merge. To do so, just uncomment the entries below
-###############################################################################
-#*.sln merge=binary
-#*.csproj merge=binary
-#*.vbproj merge=binary
-#*.vcxproj merge=binary
-#*.vcproj merge=binary
-#*.dbproj merge=binary
-#*.fsproj merge=binary
-#*.lsproj merge=binary
-#*.wixproj merge=binary
-#*.modelproj merge=binary
-#*.sqlproj merge=binary
-#*.wwaproj merge=binary
-
-###############################################################################
-# behavior for image files
-#
-# image files are treated as binary by default.
-###############################################################################
-#*.jpg binary
-#*.png binary
-#*.gif binary
-
-###############################################################################
-# diff behavior for common document formats
-#
-# Convert binary document formats to text before diffing them. This feature
-# is only available from the command line. Turn it on by uncommenting the
-# entries below.
-###############################################################################
-#*.doc diff=astextplain
-#*.DOC diff=astextplain
-#*.docx diff=astextplain
-#*.DOCX diff=astextplain
-#*.dot diff=astextplain
-#*.DOT diff=astextplain
-#*.pdf diff=astextplain
-#*.PDF diff=astextplain
-#*.rtf diff=astextplain
-#*.RTF diff=astextplain
diff --git a/BonNotiz/BonNotiz.csproj b/BonNotiz/BonNotiz.csproj
index b73b207..b3ea26d 100644
--- a/BonNotiz/BonNotiz.csproj
+++ b/BonNotiz/BonNotiz.csproj
@@ -7,9 +7,27 @@
net10.0-windows
enable
true
+ true
disable
BonNotiz.Program
none
+ BonNotiz.ico
+
BonNotiz
+ Anna Christina Naß
+
+ LICENSE.txt
+
+
+
+
+
+
+ True
+ \
+
+
+
+
\ No newline at end of file
diff --git a/BonNotiz/BonNotiz.ico b/BonNotiz/BonNotiz.ico
new file mode 100644
index 0000000..7d36a8f
Binary files /dev/null and b/BonNotiz/BonNotiz.ico differ
diff --git a/BonNotiz/EscPosPrinter.cs b/BonNotiz/EscPosPrinter.cs
index 0178234..9da5c88 100644
--- a/BonNotiz/EscPosPrinter.cs
+++ b/BonNotiz/EscPosPrinter.cs
@@ -3,7 +3,7 @@ using System.Text;
using System.IO;
using System.Drawing;
-namespace KohaCompanion.Shared
+namespace BonNotiz
{
///
/// Stellt einen zustandsbehafteten ESC/POS-Drucker dar.
@@ -34,10 +34,10 @@ namespace KohaCompanion.Shared
public class PrinterCodepage
{
- public static readonly PrinterCodepage Cp437 = new PrinterCodepage(0, CodePagesEncodingProvider.Instance.GetEncoding(437));
- public static readonly PrinterCodepage Cp852 = new PrinterCodepage(18, CodePagesEncodingProvider.Instance.GetEncoding(852));
- public static readonly PrinterCodepage Cp866 = new PrinterCodepage(17, CodePagesEncodingProvider.Instance.GetEncoding(866));
- public static readonly PrinterCodepage Cp1252 = new PrinterCodepage(16, CodePagesEncodingProvider.Instance.GetEncoding(1252));
+ public static readonly PrinterCodepage Cp437 = new(0, CodePagesEncodingProvider.Instance.GetEncoding(437));
+ public static readonly PrinterCodepage Cp852 = new(18, CodePagesEncodingProvider.Instance.GetEncoding(852));
+ public static readonly PrinterCodepage Cp866 = new(17, CodePagesEncodingProvider.Instance.GetEncoding(866));
+ public static readonly PrinterCodepage Cp1252 = new(16, CodePagesEncodingProvider.Instance.GetEncoding(1252));
private readonly byte _pageNumber;
private readonly Encoding? _encoding;
@@ -52,8 +52,10 @@ namespace KohaCompanion.Shared
public Encoding Encoding { get { return _encoding; } }
}
- // Steuercodes für neue Zeile
- private static readonly byte[] newLineBytes = { 0xA, 0xD };
+ // Steuercodes
+ private static readonly byte[] newLineBytes = [0xA, 0xD];
+ private static readonly byte esc = 0x1b;
+ private static readonly byte gs = 0x1d;
// Interner Buffer
private MemoryStream memstr = new();
@@ -63,10 +65,8 @@ namespace KohaCompanion.Shared
private bool underline = false;
private bool underlineDouble = false;
private bool emphasized = false;
- //private bool redColor = false; * unused
private int currentFontX = 0;
private int currentFontY = 0;
- //private bool panelButtonsEnabled = true; * unused
private Alignment _alignment = Alignment.Left;
///
@@ -80,7 +80,7 @@ namespace KohaCompanion.Shared
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
// Initialize Printer Command senden
- byte[] buf = new byte[] { 0x1B, 0x40 };
+ byte[] buf = [esc, 0x40];
memstr.Write(buf, 0, buf.Length);
}
@@ -119,12 +119,10 @@ namespace KohaCompanion.Shared
byte[] buf = printerEnc.Encoding.GetBytes(str);
// Aufpassen, dass kein ASCII-Steuerzeichen vorkommt.
- // For i As Integer = 0 To buf.Length - 1
- // Dim c As Byte = buf(i)
- // If Not (c >= &H20 AndAlso c <> &H7F) Then
- // buf(i) = CByte(AscW(" "c))
- // End If
- // Next
+ for (int i = 0; i < buf.Length; i++) {
+ if ((int)buf[i] < 0x20 || (int)buf[i] == 0x7F)
+ buf[i] = 0x20;
+ }
memstr.Write(buf, 0, buf.Length);
}
@@ -170,7 +168,7 @@ namespace KohaCompanion.Shared
byte[] buf;
- byte[] zeilenAnfang = new byte[] { 0x1B, 0x2A, 33, System.Convert.ToByte(bmp.Width & 0xFF), System.Convert.ToByte((bmp.Width >> 8) & 0xFF) };
+ byte[] zeilenAnfang = [esc, 0x2A, 33, System.Convert.ToByte(bmp.Width & 0xFF), System.Convert.ToByte((bmp.Width >> 8) & 0xFF)];
byte[] bildBuf = new byte[bmp.Width * 3 - 1 + 1];
for (int i = 0; i <= bmp.Height / 24 - 1; i++)
@@ -201,10 +199,10 @@ namespace KohaCompanion.Shared
// Zeile, aber geht mit kleineren Werten auch)
// Nicht LF verwenden, weil bei LF der normale Zeilenabstand verwendet
// wird!
- buf = new byte[] { 0x1B, 0x4A, 0 };
+ buf = [esc, 0x4A, 0];
else
// Am Schluss normaler Zeilenabstand nach unten.
- buf = new byte[] { 0xA };
+ buf = [0xA];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -217,13 +215,13 @@ namespace KohaCompanion.Shared
/// sonst false
/// true, wenn die Linie 2 Pixel statt 1 Pixel
/// dick sein soll
- public void SetUnderline(bool value, bool doubleThickness)
+ public void SetUnderline(bool value, bool doubleThickness = false)
{
if (value != underline || (value & doubleThickness != underlineDouble))
{
underline = value;
underlineDouble = doubleThickness;
- byte[] buf = new byte[] { 0x1B, 0x2D, System.Convert.ToByte(value ? doubleThickness ? 2 : 1 : 0) };
+ byte[] buf = [esc, 0x2D, System.Convert.ToByte(value ? doubleThickness ? 2 : 1 : 0)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -238,7 +236,7 @@ namespace KohaCompanion.Shared
if (value != emphasized)
{
emphasized = value;
- byte[] buf = new byte[] { 0x1B, 0x45, System.Convert.ToByte(value ? 1 : 0) };
+ byte[] buf = [esc, 0x45, System.Convert.ToByte(value ? 1 : 0)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -260,7 +258,7 @@ namespace KohaCompanion.Shared
currentFontX = x;
currentFontY = y;
- byte[] buf = new byte[] { 0x1D, 0x21, System.Convert.ToByte((x << 4) | y) };
+ byte[] buf = [gs, 0x21, System.Convert.ToByte((x << 4) | y)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -274,7 +272,7 @@ namespace KohaCompanion.Shared
if (printerEnc != codepage)
{
printerEnc = codepage;
- byte[] buf = new byte[] { 0x1B, 0x74, codepage.PageNumber };
+ byte[] buf = [esc, 0x74, codepage.PageNumber];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -289,7 +287,7 @@ namespace KohaCompanion.Shared
if (_alignment != alignment)
{
_alignment = alignment;
- byte[] buf = new byte[] { 0x1B, 0x61, System.Convert.ToByte(alignment) };
+ byte[] buf = [esc, 0x61, System.Convert.ToByte(alignment)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -303,7 +301,7 @@ namespace KohaCompanion.Shared
/// werden soll
public void CutPaper(bool fullCut)
{
- byte[] buf = new byte[] { 0x1D, 0x56, System.Convert.ToByte(fullCut ? 65 : 66), 0x40 };
+ byte[] buf = [gs, 0x56, System.Convert.ToByte(fullCut ? 65 : 66), 0x40];
memstr.Write(buf, 0, buf.Length);
}
diff --git a/BonNotiz/Main.Designer.cs b/BonNotiz/Main.Designer.cs
index ed51b97..6154647 100644
--- a/BonNotiz/Main.Designer.cs
+++ b/BonNotiz/Main.Designer.cs
@@ -31,9 +31,11 @@ namespace BonNotiz
///
private void InitializeComponent()
{
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
TextBox = new TextBox();
PrinterSelect = new ComboBox();
Print = new Button();
+ Info = new Button();
SuspendLayout();
//
// TextBox
@@ -58,23 +60,38 @@ namespace BonNotiz
//
// Print
//
- Print.Location = new Point(407, 357);
+ Print.Location = new Point(389, 357);
Print.Name = "Print";
- Print.Size = new Size(75, 23);
+ Print.Size = new Size(93, 23);
Print.TabIndex = 3;
Print.Text = "&Drucken";
Print.UseVisualStyleBackColor = true;
Print.Click += Print_Click;
//
+ // Info
+ //
+ Info.Location = new Point(245, 357);
+ Info.Name = "Info";
+ Info.Size = new Size(109, 23);
+ Info.TabIndex = 4;
+ Info.Text = "&Info...";
+ Info.UseVisualStyleBackColor = true;
+ Info.Click += Info_Click;
+ //
// Main
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(493, 391);
+ Controls.Add(Info);
Controls.Add(Print);
Controls.Add(PrinterSelect);
Controls.Add(TextBox);
+ FormBorderStyle = FormBorderStyle.FixedSingle;
+ Icon = (Icon)resources.GetObject("$this.Icon");
+ MaximizeBox = false;
Name = "Main";
+ SizeGripStyle = SizeGripStyle.Hide;
Text = "BonNotiz";
ResumeLayout(false);
PerformLayout();
@@ -85,5 +102,6 @@ namespace BonNotiz
private TextBox TextBox;
private ComboBox PrinterSelect;
private Button Print;
+ private Button Info;
}
}
diff --git a/BonNotiz/Main.cs b/BonNotiz/Main.cs
index b4c4481..c53d9f0 100644
--- a/BonNotiz/Main.cs
+++ b/BonNotiz/Main.cs
@@ -1,4 +1,3 @@
-using KohaCompanion.Shared;
using System;
using System.Windows.Forms;
@@ -32,13 +31,16 @@ namespace BonNotiz
static void Drucken(String bondrucker, String text)
{
- EscPosPrinter pos = new();
+ /* EscPosPrinter pos = new();
pos.Write(text);
pos.WriteLine();
pos.WriteLine();
pos.CutPaper(true);
- Byte[] buf = pos.GetCurrentBuffer();
+ Byte[] buf = pos.GetCurrentBuffer(); */
+
+ MarkdownToEscPos md = new();
+ Byte[] buf = md.Render(text);
using RawPrinter prn = new(bondrucker);
using RawPrinter.RawDocumentStream doc = prn.CreateDocument("BonNotiz");
@@ -56,5 +58,21 @@ namespace BonNotiz
Drucken(PrinterSelect.SelectedItem.ToString()!, TextBox.Text);
}
}
+
+ private void Info_Click(object sender, EventArgs e)
+ {
+ String text = "BonNotiz\n(c) 2026 Anna Christina Naß\n\n"
+ + "Folgende Markdown-Formatierungen werden umgesetzt:\n\n"
+ + "# Überschrift 1\n"
+ + "## Überschrift 2\n"
+ + "### Überschrift 3 (und weitere analog)\n"
+ + "--- (Horizontale Linie)\n"
+ + "- Aufzählung\n"
+ + "**fett**\n"
+ + "*kursiv* (wird ebenfalls fett gedruckt)\n"
+ + "_unterstrichen_";
+
+ MessageBox.Show(text, "Über BonNotiz", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
}
}
diff --git a/BonNotiz/Main.resx b/BonNotiz/Main.resx
index 8b2ff64..d91ce66 100644
--- a/BonNotiz/Main.resx
+++ b/BonNotiz/Main.resx
@@ -117,4 +117,171 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACkAAAA5AAAAOQAA
+ ADkAAAA5AAAAOQAAADkAAAA5AAAAOQAAADkAAAA5AAAAOQAAADkAAAA5AAAAOgAAEkYhJUK9ISVAtgAA
+ E0wAAAA6AAAAOQAAADkAAAA5AAAAOQAAADkAAAAoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAA
+ AGOrq6vCsbGxw7GxscOxsbHDsbGxw7GxscOxsbHDsbGxw7GxscOxsbHDsbGxw7GxscOxsbHDsLCww1J6
+ peVHhbH+Jk19+GJmd+CqqqrFsbGxw7GxscOxsbHDsbGxw6urq8IAAABjAAAADwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAACgAAAFzs7Ozs////////////////////////////////////////////////////////
+ /////////////zdlpP9NwN7/GEqN/05gff/Gys//+/v7/////////////////+zs7OsAAABcAAAACgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAB6enr/d3d3/1VVVf/FxcX/////////////////////////////////////////
+ /////////////////////////////36gy/8lirv/L7nh/xlNkv9rc4T/5+ft//7+/v///////////8TE
+ xP9VVVX/d3d3/3p6ev8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6enr/fn5+53V1demvr6/5+vn5//39/f//////////////
+ //////////////////////////////////////////////D0+P8aRoX/ONj3/yB4rv8wW47/lZmo//j4
+ +P/9/f3/+vn5/66urvh2dnbpfn5+53p6ev8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEhIT/hISE/7Gxsf+lpKT/9fT0//j3
+ 9//6+vr//f39//////////////////////////////////////////////////////8yX5//Kbrn/yXF
+ 7P8XUJb/TWF+/8LGy//08/P/9fT0/6Sjo/+wsLD/g4OD/4SEhP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOjo7/d3d3/4yM
+ jP9+fX3/7evr//Hv7//08/P/9/b2//n5+f/7+vr//Pz8//79/f//////////////////////////////
+ //+GpMz/IXmt/xSy6/8nrdr/G1eY/2tzgv/b2d7/7Orq/359ff+NjY3/d3d3/46Ojv8AAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AADm5ub/jIyM/1lZWf9UU1P/5OLi/+jm5v/s6ur/7+3t//Lw8P/08/P/9vX1//f29v/49/f/+fj4//n4
+ +P/5+Pj/+fj4//j39//u7/L/F0J+/yG78P8St+j/H3u0/zFgjv+Ljpz/3tzc/1RUVP9ZWVn/jIyM/+bm
+ 5v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAADd3d3/gICA/y4uLv8oJyf/19TU/9/c3P/i4OD/5ePj/+jm5v/q6en/7Ovr/+7s
+ 7P/v7u7/8O/v//Hv7//x7+//8O/v/+/u7v/u7Oz/NF+a/yGv3/8CoeP/IL/p/xhdn/9JXHn/qauw/ycm
+ Jv8uLi7/gICA/93d3f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkIiIH5aQ
+ kPSbmpr+m5qa/puamv6bmpr+m5qa/n18fP7n5+f/hYWF/yEhIf8XFxf/s7Cw/9TQ0P/Y1NT/29jY/9/c
+ 3P/h3t7/4+Dg/+Ti4v/l4+P/5uTk/+bk5P/m5OT/5uTk/+Xj4//k4uL/gJ2+/xpkl/8Sq+//BKbg/yGq
+ 2P8bY53/Vl1s/xUVGv8hISH/hYWF/+fn5/99fHz+m5qa/puamv6bmpr+m5qa/puamv6WkJD0kIiIHwAA
+ AAAAAAAAkYeHMqahof++vr7/vr6+/76+vv++vr7/vr6+/5iYmP/w8PD/iYmJ/yEhIf8YGBj/j4yM/8jD
+ w//Mx8f/z8vL/9LOzv/V0dH/19PT/9nV1f/a19f/29jY/9vY2P/b2Nj/29jY/9rX1//Z1dX/08/R/xY/
+ eP8dufD/AqTj/w636P8agrn/KF6G/x0gL/8gICD/iYmJ//Dw8P+YmJj/vr6+/76+vv++vr7/vr6+/76+
+ vv+moaH/jYeHMAAAAAAAAAAAlo+PQ7GsrP/Hx8f/x8fH/8fHx//Hx8f/x8fH/6Ojo//6+vr/ioqK/xsb
+ G/8VFRX/YV5e/6WgoP+oo6P/qqam/62oqP+vq6v/sa2t/7Ourv+0sLD/tbGx/7Wxsf+1sbH/tbGx/7Sw
+ sP+zrq7/sa2t/y5Zi/8co9T/BqTr/wCp4f8Yvun/FG2p/xw0TP8dISb/iIiI//r6+v+jo6P/x8fH/8fH
+ x//Hx8f/x8fH/8fHx/+wrKz/l4uLQQAAAAAAAAAApp2dVcC9vf/R0dH/0dHR/9HR0f/R0dH/0dHR/6+v
+ r///////hoaG/w0NDf8LCwv/CQkJ/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgI
+ CP8ICAj/CAgI/wgICP8ICAj/CAgI/womQP8YUX//FLHx/wGq5P8Dr+T/G6va/xZpm/8dJTT/e3uA//7+
+ /v+vr6//0dHR/9HR0f/U1NT/0tLS/9HR0f+/vLz/pp2dUgAAAAAAAAAAtK+vZc/Nzf/b29v/29vb/9vb
+ 2//b29v/29vb/8PDw/98fHz/QkJC/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgI
+ CP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8SOWv/Gbbs/waq6/8Ar+T/Cbzq/xiN
+ v/8YU3b/MzlD/3l5ef/FxcX/29vb/9vb2/+1tbX/o6Oj/9vb2//OzMz/tbCwYwAAAAAAAAAAxL+/btnX
+ 1//i4uL/4uLi/+Li4v/i4uL/4uLi/+Pj4/+QkJD/EBAQ/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMD
+ A/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8NO2b/GZTD/w2u
+ 8v8BsOX/ALPm/xPA6/8YgbL/GzVL/3V5f//g4OD/4uLi/+Li4v+3uLj/rq6u/+Li4v/Y1tb/xMDAawAA
+ AAAAAAAA0s3NdOLh4f/p6en/6enp/+np6f/p6en/6enp/+jo6P/b29v/5eXl/+Xl5f/l5eX/5OTk/+Pj
+ 4//i4uL/4eHh/+Dg4P/f39//3t7e/93d3f/c3Nz/29vb/9ra2v/a2tr/29vb/9zc3P/d3d3/3d3d/97e
+ 3v+Zssb/E0Bm/xK38v8Fsez/ALTm/wK56P8Vsdz/IYOr/2VtfP/V1dr/6Ojo/+np6f/Q0ND/xMTE/+np
+ 6f/j4uL/0c/PcgAAAAAAAAAA3Nrae+vq6v/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw
+ 8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw
+ 8P/w8PD/8PDw//Dw8P/v7+//Fj5p/xOz5/8LsvL/ALbo/wC56f8Fwu3/Fp3I/zh3lv+SmKL/6enp//Dw
+ 8P/Gx8f/x8fH/+3t7f/r6ur/3NnZeAAAAAAAAAAAwsDAje/u7v/29vb/9vb2//b29v/29vb/9vb2//b2
+ 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2
+ 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/19fX/Rnec/xGAqv8OtfP/Bbft/wC66f8Avuv/DMbt/xiT
+ vv9Ran//xMTL//Pz8//W1tb/yMjI//b29v/v7u7/wsDAjAAAAAAAAAAAzMzLmtPT0//R0dH/0dHR/9HR
+ 0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR
+ 0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0NDQ/8bGxv+8vML/j6S3/w0tTv8Qu/L/C7ny/wC7
+ 6v8Av+v/AMPt/xG43/8iia//Y2p5/8DAxf/Q0ND/0dHR/9HR0f/T09P/zMzKmAAAAAAAAAAA09XTcqWl
+ pf+RkZH/kZGR/5GRkf+RkZH/kZGR/5GRkf+RkZH/b29v/2JiYv9iYmL/YmJi/2JiYv9iYmL/YmJi/2Ji
+ Yv9iYmL/UlJS/1JSUv9SUlL/UlJS/1JSUv9SUlL/UlJS/1JSUv9SUlL/SUlP/y80Qv8kLT3/Ii08/xE8
+ Y/8Or9//Dbv0/wS87f8AwOz/AMPt/wDJ8P8Rpc//LGuK/19lcP+NjY3/kZGR/5GRkf+lpaX/1NTUbwAA
+ AAAAAAAA0NLSa+3u7v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/jY2N/0FBQf9BQUH/QUFB/0FB
+ Qf9BQUH/QUFB/0FBQf9BQUH/YmJi/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9kZGT/Q3SV/0uR
+ t/8ZV5P/GV+a/xZRgv8Na4//Db30/wu/8v8Awez/AMTu/wDI7/8DyvD/FpnG/1VrgP/IzNH/9/f3//r6
+ +v/t7u3/0dTRaAAAAAAAAAAAzdLQX+jq6f/39/f/9/f3//f39//39/f/9/f3//f39//39/f/mJiY/1BQ
+ UP9QUFD/UFBQ/1BQUP9QUFD/UFBQ/1BQUP9QUFD/ZmZm/3h4eP93d3f/d3d3/3d3d/93d3f/d3d3/3d3
+ d/94eHj/Jl2Q/yCLxf8Vr/L/DrDy/wy28/8Nu/T/Dr71/w7B9f8Dwu//AMbu/wDJ8P8AzPH/Cbrj/yOM
+ tf9qc4f/4+Po//b29v/o6en/ztHOXQAAAAAAAAAAzNDMT+Pl5f/09PT/9PT0//T09P/09PT/9PT0//T0
+ 9P/09PT/m5ub/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VV
+ Vf9VVVX/VVVV/1VVVf9VVVX/Olp1/xZPjf8ZsfL/Jrjz/yy/9f8owvX/Lcf2/zvO+P890/j/EMvw/wDK
+ 8P8AzvL/ANL0/w6j1v86dJj/mZyn/+7u7v/j5eT/ytHOTAAAAAAAAAAAxsrKPd3f3v/x8fH/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/x8fH/np6e/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VV
+ Vf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VFVV/xdQj/8JpuX/C7Dy/w228/8Wy/r/FdP9/xjW
+ /f8c2P3/QuH9/2Di+v9J3vf/BdP0/wLQ8/8Tks7/U2qC/9bW2f/b3t3/xMjIOwAAAAAAAAAAu8fBLNbZ
+ 1//u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/0NDQ/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm
+ 5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/0J9sf8OhcP/C7Dy/wy2
+ 8/8Kwff/ANX//wDX//8A2P//ANr//wDb//8Y3///XOf9/1Lm+/8Ouej/Koe8/9fc3P/U2Nb/vsS+KgAA
+ AAAAAAAAqqqqF8TGxc3f4ODi3+Hg4uDi4eLh4+Li4uPj4uLk4+Li5OPiqKio8oaHh/CGh4fwh4eH8IeH
+ h/CHh4fwh4mH8IeJh/CHiYfwh4mJ8IeJifCHiYnwh4mJ8IeJifCHiYnwh4mJ8IeJifCHiYnwh4mJ8Fh6
+ lvUVVJP/CrLz/wy28/8OvfX/A9H9/wDX//8A2f//ANr//wm85P8LtuH/Crjj/xm95/9h0fD/icfo/N7f
+ 3+LExsXNqqqqFwAAAAAAAAAAAAAAAJOTk+ucnJz/pKSk/6urq/+zs7P/u7u7/76+vv/AwMD/d3d3/0FB
+ Qf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FB
+ Qf9BQUH/QUFB/z9AQv8WVJP/Cqzq/wy28/8OvfX/Csn5/wDY//8A2f//ANv//wm+5/8Vj8H/KWeJ/2OZ
+ tv9soLv/laSt/5ycnP+Tk5PsAAAAAAAAAAAAAAAAAAAAAJCQkL2YmJj/n5+f/6enp/+urq7/tra2/7y8
+ vP++vr7/aGho/0RERP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BA
+ QP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP8cW47/DY7K/wy28/8OvfX/D8T2/wLW/v8A2f//ANv//wHb
+ /v8Rn9D/H2SI/2Noc/+ioqL/n5+f/5iYmP+Pj4+8AAAAAAAAAAAAAAAAAAAAAImJiY6Tk5P/m5ub/6Ki
+ ov+pqan/sLCw/7e3t/+8vLz/aWlp/ycnJ/9YVVX/WVZW/1tYWP9cWlr/XVpa/11bW/9eXFz/Xlxc/19d
+ Xf9gXl7/YF5e/2BeXv9gXl7/YF5e/2BeXv9fXV3/Xlxc/15cXP8+YHz/FFyb/wu39P8OvfX/D8T2/wnQ
+ +v8A2v//ANv//wDd//8KyvD/EonD/zJFVf+JiYz/mpqa/5OTk/+KioqNAAAAAAAAAAAAAAAAAAAAAIiI
+ iF+Ojo7/lpaW/52dnf+kpKT/q6ur/7Kysv+4uLj/dnZ2/yUlJf+1r6//urS0/764uP/BvLz/xcDA/8fD
+ w//KxcX/zMjI/87Kyv/Py8v/0MzM/9DMzP/QzMz/0MzM/8/Ly//Oysr/zMjI/8rFxf/Cv8H/GV2b/wqz
+ 7P8NvPT/D8P2/w/L9/8B2f//ANz//wDd//8C3///EabZ/xhrnP9NUF3/kJCQ/46Ojv+GhoZeAAAAAAAA
+ AAAAAAAAAAAAAIeHhzCJiYn/kJCQ/5eXl/+enp7/paWl/6ysrP+ysrL/rq6u/ysrK/+9t7f/wby8/8XA
+ wP/JxcX/zMjI/8/Ly//Szs7/1NHR/9bT0//X1NT/2NXV/9nV1f/Z1dX/2NXV/9fU1P/W0tL/1NHR/9LO
+ zv/Py8v/PHqu/w2V0P8NvPT/D8P2/xDK9/8I1vz/ANz//wDe//8A3///C9b2/xCIzP8kRl7/a3B2/4eH
+ h/+FhYUvAAAAAAAAAAAAAAAAAAAAAG1tbQaIiIiIioqKiJGRkYiXl5eInp6eiKSkpIirq6uInJyc9jEx
+ Mf/Ev7//ycTE/83Jyf/Rzc3/1NHR/9fU1P/a19f/3dnZ/97b2//f3Nz/4N3d/+De3v/g3t7/4N3d/9/c
+ 3P/e29v/3dnZ/9rX1//X1NT/hafD/xRjo/8Nu/T/D8L2/xDK9/8P0vn/ANz//wDe//8A4P//AeH//xKu
+ 4v8Rbqz+MDdK5Hd3d5FtbW0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAmZmZ5TY2Nv/Lx8f/0MzM/9TR0f/Y1dX/3NnZ/9/c3P/h39//4+Hh/+Xi4v/m4+P/5+Tk/+fl
+ 5f/n5eX/5+Tk/+bj4//l4uL/4+Hh/+Hf3//f3Nz/1tbX/xhen/8LuO//DsL1/xDJ9/8R0fj/Btv9/wDe
+ //8A4P//AOL//wzd+/8NhtT/GUZw9CYsOnEAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAnJyc3z09Pf/Sz8//19TU/9zZ2f/g3d3/4+Dg/+Xj4//n5eX/6efn/+vp
+ 6f/s6ur/7evr/+3s7P/t7Oz/7evr/+zq6v/r6en/6efn/+fl5f/l4+P/4+Dg/0B/tf8NnNb/DsD1/xDI
+ 9/8R0Pj/D9j6/wDf//8A4P//AOL//wDj//8buuv/C26+/iUsQNwAKiojAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo6Oj1URERP/Z1tb/3tvb/+Lf3//l4+P/6Obm/+vp
+ 6f/u7Oz/8O7u//Hw8P/z8fH/8/Ly//Tz8//08/P/8/Ly//Px8f/x8PD/8O7u/+7s7P/r6en/6Obm/42w
+ zv8Raav/DsD1/w/H9v8Rz/j/Etf5/wXf/v8A4P//AOL//wDk//8R5f7/FYzb/xVMhvgbLjyTAAAACAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJyc1UlJSf/g3d3/5OHh/+jl
+ 5f/r6en/7u3t//Hw8P/08/P/9vX1//f29v/49/f/+Pj4//n4+P/5+Pj/+Pj4//j39//39vb/9vX1//Ty
+ 8v/x8PD/7u3t/+Xl5/8YX6T/C7zx/w/F9v8Rzvj/Etb5/w7e/P8A4P//AOL//wDk//8A5v//K8ny/wdr
+ zv8fM0jqISEyPAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlpaW1FNT
+ U//l4uL/6efn/+3r6//x7+//9PPz//f29v/4+Pj/+vn5//v7+//8/Pz//Pz8//39/f/9/f3//Pz8//z8
+ /P/7+/v/+vn5//j4+P/39vb/9PPz//Hv7/9CgLr/C5/b/w/D9v8QzPf/EtX5/xPd+v8D4v//AOL//wDk
+ //8A5v//Euj//ySX4/8PUZn8IilAswAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAcnJyUkZGRsPq6Oj/7u3t//Lx8f/29fX/+Pj4//r6+v/8/Pz//v7+////////////////////
+ /////////////////////////v7+//z8/P/6+vr/+Pj4//b19f+Rtdb/D22z/w7B9f8Qyvf/EtP5/xPc
+ +v8N4v3/AOL//wDk//8A5v//AOf//z3Z+P8FbNn/HDVa8RspOlsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGjv7e3/8/Ly//f29v/6+fn//Pz8//7+/v//////////////
+ ///////////////////////////////////////////////////+/v7//Pz8//r5+f/u8fT/Fl2o/wu+
+ 8/8Px/b/EdH4/xPa+v8T4/v/AuP//wDk//8A5f//AOf//wvp//87re3/C1qx/iEqOswAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj08vL/9/f3//r6+v/9/f3/////////
+ //////////////////////////////////////////////////////////////////////////////39
+ /f/6+vr/Q4C//wqj3v8PxPb/Ec74/xLX+f8U4fv/C+b+/wDj//8A5f//AOb//wDn//9F4vv/CnXi/xpA
+ c90AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj39/f/+/r6//79
+ /f//////////////////////////////////////////////////////////////////////////////
+ ///////////////////+/f3/ob/i/3Ck0v80seL/NbXl/ze55/84ven/Ob3p/zax5/81sun/NbTr/zW1
+ 7f84t/D/jsvy/zGA2I8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAA
+ AGj6+vr//f39////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////f39/6TB4/8GQ4e4CViujQdev4EIYMF+BmHGewZi
+ x3kEZcx2BGPPcwRn0HECZ9ZuAmrZXSBgwAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAEgAAAGj9/f3/////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////39/f8AAABoAAAAEgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj/////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //8AAABoAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj/////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////8AAABoAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAE4AAABoAAAAaAAA
+ AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAA
+ AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABOAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAoAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAA
+ ABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAKAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/
+ AAD/gAAAAf8AAP+AAAAB/wAA/4AAAAH/AAD/gAAAAf8AAP+AAAAB/wAA/4AAAAH/AACAAAAAAAEAAIAA
+ AAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB
+ AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA
+ AAAAAQAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAA/8AAAAAD
+ AAD/wAAAAAEAAP/AAAAAAQAA/8AAAAAAAAD/wAAAAAAAAP/AAAAAAAAA/8AAAAAAAAD/wAAAAAAAAP/A
+ AAAAAAAA/8AAAAAAAAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/gAAAH/wAA////////
+ AAA=
+
+
\ No newline at end of file
diff --git a/BonNotiz/MarkdownToEscPos.cs b/BonNotiz/MarkdownToEscPos.cs
new file mode 100644
index 0000000..edc4b0d
--- /dev/null
+++ b/BonNotiz/MarkdownToEscPos.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using static BonNotiz.MiniMarkdown;
+
+namespace BonNotiz
+{
+ public class MarkdownToEscPos
+ {
+ private readonly EscPosPrinter epp;
+
+ public MarkdownToEscPos()
+ {
+ epp = new();
+ }
+
+ public byte[] Render(String text)
+ {
+ MdDocument doc = MiniMarkdown.Parse(text);
+
+ return Render(doc);
+ }
+
+ public byte[] Render(MdDocument doc)
+ {
+ foreach (MdBlock block in doc.Blocks)
+ RenderBlock(block);
+
+ epp.WriteLine();
+ epp.CutPaper(true);
+
+ return epp.GetCurrentBuffer();
+ }
+
+ private void RenderBlock(MdBlock block)
+ {
+ switch (block)
+ {
+ case MdHeading h:
+ switch (h.Level)
+ {
+ case 1:
+ epp.SetFontSize(1, 1);
+ break;
+ case 2:
+ epp.SetFontSize(1, 0);
+ break;
+ default:
+ epp.SetFontSize(0, 1);
+ break;
+ }
+ RenderInline(h.Content);
+ epp.WriteLine();
+ epp.WriteLine();
+ epp.SetFontSize(0, 0);
+ break;
+
+ case MdParagraph p:
+ RenderInline(p.Content);
+ epp.WriteLine();
+ epp.WriteLine();
+ break;
+
+ case MdList l:
+ foreach (var item in l.Items)
+ {
+ epp.Write(new string([(char)0xBB, ' ']));
+ RenderInline(item.Content);
+ epp.WriteLine();
+ }
+ break;
+
+ case MdHorizontalRule:
+ epp.WriteLine(new string((char)0x2550, 42));
+ break;
+ }
+ }
+
+ private void RenderInline(List inlines)
+ {
+ foreach (var inline in inlines)
+ {
+ switch (inline)
+ {
+ case MdText t:
+ epp.Write(t.Value);
+ break;
+
+ case MdBold b:
+ epp.SetEmphasized(true);
+ RenderInline(b.Content);
+ epp.SetEmphasized(false);
+ break;
+
+ case MdItalic i:
+ epp.SetEmphasized(true);
+ RenderInline(i.Content);
+ epp.SetEmphasized(false);
+ break;
+
+ case MdUnderline u:
+ epp.SetUnderline(true);
+ RenderInline(u.Content);
+ epp.SetUnderline(false);
+ break;
+ }
+ }
+ }
+ }
+
+}
diff --git a/BonNotiz/MiniMarkdown.cs b/BonNotiz/MiniMarkdown.cs
new file mode 100644
index 0000000..7e857b3
--- /dev/null
+++ b/BonNotiz/MiniMarkdown.cs
@@ -0,0 +1,156 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace BonNotiz
+{
+ public static class MiniMarkdown
+ {
+ public abstract record MdBlock;
+ public record MdDocument(List Blocks) : MdBlock;
+ public record MdHeading(int Level, List Content) : MdBlock;
+ public record MdParagraph(List Content) : MdBlock;
+ public record MdList(List Items) : MdBlock;
+ public record MdListItem(List Content);
+ public record MdHorizontalRule() : MdBlock;
+ public abstract record MdInline;
+ public record MdText(string Value) : MdInline;
+ public record MdBold(List Content) : MdInline;
+ public record MdItalic(List Content) : MdInline;
+ public record MdUnderline(List Content) : MdInline;
+
+ public static MdDocument Parse(string markdown)
+ {
+ List blocks = [];
+ List listBuffer = [];
+
+ string[] lines = markdown.Replace("\r\n", "\n").Split('\n');
+
+ // Wenn listBuffer etwas enthält, dieses an blocks anhängen und listBuffer leeren
+ void FlushList()
+ {
+ if (listBuffer.Count > 0)
+ {
+ blocks.Add(new MdList(listBuffer.ToList()));
+ listBuffer.Clear();
+ }
+ }
+
+ foreach (string rawLine in lines)
+ {
+ string line = rawLine.TrimEnd();
+
+ if (string.IsNullOrWhiteSpace(line))
+ {
+ FlushList();
+ continue;
+ }
+
+ // Horizontal rule
+ if (line.StartsWith("---"))
+ {
+ FlushList();
+ blocks.Add(new MdHorizontalRule());
+ continue;
+ }
+
+ // Heading
+ if (line.StartsWith('#'))
+ {
+ FlushList();
+
+ int level = line.TakeWhile(c => c == '#').Count();
+ string text = line[level..].Trim();
+
+ blocks.Add(new MdHeading(level, ParseInline(text)));
+ continue;
+ }
+
+ // List item
+ if (line.StartsWith("- "))
+ {
+ listBuffer.Add(new MdListItem(ParseInline(line[2..])));
+ continue;
+ }
+
+ // Paragraph
+ FlushList();
+ blocks.Add(new MdParagraph(ParseInline(line)));
+ }
+
+ FlushList();
+
+ return new MdDocument(blocks);
+ }
+
+ private static List ParseInline(string text)
+ {
+ List result = [];
+
+ int i = 0;
+
+ while (i < text.Length)
+ {
+ // Bold **
+ if (i + 1 < text.Length && text[i] == '*' && text[i + 1] == '*')
+ {
+ int end = text.IndexOf("**", i + 2);
+ if (end == -1) break;
+
+ string inner = text[(i + 2)..end];
+ result.Add(new MdBold(ParseInline(inner)));
+
+ i = end + 2;
+ continue;
+ }
+
+ // Italic *
+ if (text[i] == '*')
+ {
+ int end = text.IndexOf('*', i + 1);
+ if (end == -1) break;
+
+ string inner = text[(i + 1)..end];
+ result.Add(new MdItalic(ParseInline(inner)));
+
+ i = end + 1;
+ continue;
+ }
+
+ // Underline _
+ if (i + 1 < text.Length && text[i] == '_')
+ {
+ int end = text.IndexOf("_", i + 1);
+ if (end == -1) break;
+
+ string inner = text[(i + 1)..end];
+ result.Add(new MdUnderline(ParseInline(inner)));
+
+ i = end + 1;
+ continue;
+ }
+
+ // Plain text
+ int nextSpecial = FindNextSpecial(text, i);
+ result.Add(new MdText(text[i..nextSpecial]));
+ i = nextSpecial;
+ }
+
+ return result;
+ }
+
+ private static int FindNextSpecial(string text, int start)
+ {
+ int[] candidates = [ text.IndexOf('*', start), text.IndexOf("_", start) ];
+
+ int min = int.MaxValue;
+
+ foreach (var c in candidates)
+ if (c != -1 && c < min)
+ min = c;
+
+ return min == int.MaxValue ? text.Length : min;
+ }
+ }
+
+}
+
diff --git a/BonNotiz/RawPrinter.cs b/BonNotiz/RawPrinter.cs
index d0820d2..d32cf08 100644
--- a/BonNotiz/RawPrinter.cs
+++ b/BonNotiz/RawPrinter.cs
@@ -2,7 +2,7 @@
using System.IO;
using System.Runtime.InteropServices;
-namespace KohaCompanion.Shared
+namespace BonNotiz
{
///
/// Eine Klasse zum Kapseln eines Druckers. Mit der Methode