From 5de1d8fc0798837fc4bfa1b2685824662e5db90c Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Mon, 5 May 2025 13:48:51 +0200 Subject: [PATCH] More basic stuff and features --- src/Page.bf | 18 ++++ src/Pages/ExamplePage.bf | 29 ++++++ src/Pages/ImageIndexPage.bf | 62 ++++++++++++ src/Pages/IndexPage.bf | 69 +++++++++++++ src/Pages/TitlePage.bf | 51 ++++++++++ src/Program.bf | 50 +++++++++- src/Section.bf | 8 -- src/Sections/Heading.bf | 20 ---- src/Sections/Paragraph.bf | 17 ---- src/TOCItem.bf | 19 ++++ src/Writer.bf | 186 ++++++++++++++++++++++++++++++------ 11 files changed, 449 insertions(+), 80 deletions(-) create mode 100644 src/Page.bf create mode 100644 src/Pages/ExamplePage.bf create mode 100644 src/Pages/ImageIndexPage.bf create mode 100644 src/Pages/IndexPage.bf create mode 100644 src/Pages/TitlePage.bf delete mode 100644 src/Section.bf delete mode 100644 src/Sections/Heading.bf delete mode 100644 src/Sections/Paragraph.bf create mode 100644 src/TOCItem.bf diff --git a/src/Page.bf b/src/Page.bf new file mode 100644 index 0000000..55eac82 --- /dev/null +++ b/src/Page.bf @@ -0,0 +1,18 @@ +namespace Writer; + +using System; + +abstract class Page +{ + private String _content = new .() ~ delete _; + + public virtual void ComputeStyle(StringView className, String buffer) + { + } + + public virtual void ComputeContent(String buffer) => buffer.Append(_content); + + public void AddHeading(uint8 n, StringView content) => _content.Append(scope $"{content}"); + public void AddParagraph(StringView content) => _content.Append(scope $"
{content}
"); + public void AddCode(StringView code) => _content.Append(scope $"{code}"); +} \ No newline at end of file diff --git a/src/Pages/ExamplePage.bf b/src/Pages/ExamplePage.bf new file mode 100644 index 0000000..cdf0153 --- /dev/null +++ b/src/Pages/ExamplePage.bf @@ -0,0 +1,29 @@ +namespace Writer; + +using System; + +class ExamplePage : Page +{ + public this() + { + this.AddHeading(1, "Writer - documents to pdf"); + this.AddParagraph(""" + Write Beef code to create printable html documents and convert them into pdf files for things like essays. + """); + this.AddCode(""" + using System; + class Program + { + + } + """); + } + + public override void ComputeStyle(System.StringView className, System.String buffer) + { + buffer.Append(scope $""" + .{className} \{ + \} + """); + } +} \ No newline at end of file diff --git a/src/Pages/ImageIndexPage.bf b/src/Pages/ImageIndexPage.bf new file mode 100644 index 0000000..af693cf --- /dev/null +++ b/src/Pages/ImageIndexPage.bf @@ -0,0 +1,62 @@ +namespace Writer; + +using System; +using System.Collections; + +class ImageIndexPage : Page +{ + private String Layerinfo = new .("") ~ delete _; + + public this(params Span items) + { + this.AddHeading(3, "Abbildungsverzeichnis"); + for (var i in items) + AddItem(i); + } + + public override void ComputeStyle(System.StringView className, System.String buffer) + { + buffer.Append(scope $""" + .{className} \{ + page: image-index; + \} + + + .article \{ + display: flex; + \} + .article .item, + .article .price \{ + flex: 1 0 auto; + \} + .article .dots \{ + flex: 0 1 auto; + margin: 0 5px; + /*Allows too long content to be hidden.*/ + overflow: hidden; + \} + .dots::before \{ + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: clip; + content: + ". . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . . . . " + \} + """); + } + + private void AddItem(TOCItem item) + { + this.[Friend]_content.Append(scope $""" +
+ {item.Name} + + {item.Page} +
+ """); + } +} \ No newline at end of file diff --git a/src/Pages/IndexPage.bf b/src/Pages/IndexPage.bf new file mode 100644 index 0000000..710f078 --- /dev/null +++ b/src/Pages/IndexPage.bf @@ -0,0 +1,69 @@ +namespace Writer; + +using System; +using System.Collections; + +class IndexPage : Page +{ + private String Layerinfo = new .("") ~ delete _; + + public this(params Span items) + { + this.AddHeading(3, "Inhaltsverzeichnis"); + for (var i in items) + AddItem(i, true); + } + + public override void ComputeStyle(System.StringView className, System.String buffer) + { + buffer.Append(scope $""" + .{className} \{ + page: index; + counter-reset: page 1; + \} + + + .article \{ + display: flex; + \} + .article .item, + .article .price \{ + flex: 1 0 auto; + \} + .article .dots \{ + flex: 0 1 auto; + margin: 0 5px; + /*Allows too long content to be hidden.*/ + overflow: hidden; + \} + .dots::before \{ + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: clip; + content: + ". . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . . . . " + \} + """); + } + + private void AddItem(TOCItem item, bool bold = false) + { + if (bold) + this.[Friend]_content.Append(""); + this.[Friend]_content.Append(scope $""" +
+ {item.Name} + + {item.Page} +
+ """); + if (bold) + this.[Friend]_content.Append("
"); + for (var i in item.Items) + AddItem(i); + } +} \ No newline at end of file diff --git a/src/Pages/TitlePage.bf b/src/Pages/TitlePage.bf new file mode 100644 index 0000000..83409ae --- /dev/null +++ b/src/Pages/TitlePage.bf @@ -0,0 +1,51 @@ +namespace Writer; + +using System; + +class TitlePage : Page +{ + public this(StringView title, StringView prof, StringView date) + { + this.[Friend]_content.Append(scope $""" +

+ Fachhochschule der Wirtschaft
+ -FHDW-
+ Paderborn
+


+ + Studienarbeit +


+ Thema:

+ {title} +


+ + + Prüfer:
+ prof
+

+ + Verfasser:
+ Jannis-Leander von Hagen +

+ + Wirtschaftsinformatik
+ Cyber Security

+ + Eingereicht am:
+ {date} + """); + } + + + public override void ComputeStyle(System.StringView className, System.String buffer) + { + buffer.Append(scope $""" + .{className} \{ + page: cover; + + font-size:16pt; + counter-reset: page 1; + \} + """); + } +} \ No newline at end of file diff --git a/src/Program.bf b/src/Program.bf index c4bced2..7a3dda5 100644 --- a/src/Program.bf +++ b/src/Program.bf @@ -5,10 +5,52 @@ class Program public static void Main() { Writer w = scope .(); + w.Write(scope TitlePage("Writer - Create Documents", "Unknown", "05.05.2025")); - w.AddHeading(1, "Doing things better"); - w.AddParagraph(); + w.Write(scope IndexPage( + .("Inhaltsverzeichnis", "I"), + .("Abbildungsverzeichnis", "II"), + .("1 Einleitung", "1", .("1.1 Unterpunkt", "2")) + )); - w.Output("index.html"); + w.Write(scope ImageIndexPage( + .("Abbildung 1 The origin of the world", "2") + )); + + w.Write(scope ExamplePage()); + if (w.Safe("index.html") case .Ok) + w.Convert("index.html", "result.pdf").IgnoreError(); } -} \ No newline at end of file +} +/* + + The original usecase for this library is to serve as a tool to + create scientific texts for uni. + Some code may look a bit bad, and will continue to do so until I can clean up + and make this entire thing a bit more generic. + + Requirement: + HeadingPage: + - All text centered x + - No decorations x + + Roman Pages: + - Top page with title + - Roman numeral numbering + - Index, Picture Index + + Normal Pages: + - Top page with title + - Arabic numerals + - Footnotes + - Numeric titles (1, 1.1, 2, 2.0) + + + Images: + - Subtitles + - Convert into base64 loaded image + + Codeblocks: + + +*/ \ No newline at end of file diff --git a/src/Section.bf b/src/Section.bf deleted file mode 100644 index d29262e..0000000 --- a/src/Section.bf +++ /dev/null @@ -1,8 +0,0 @@ -namespace Writer; - -using System; - -abstract class Section -{ - public abstract void Compute(String input); -} \ No newline at end of file diff --git a/src/Sections/Heading.bf b/src/Sections/Heading.bf deleted file mode 100644 index 191fa76..0000000 --- a/src/Sections/Heading.bf +++ /dev/null @@ -1,20 +0,0 @@ -namespace Writer.Sections; - -using System; - -class Heading : Section -{ - public uint8 Level = 1; - public String Name = new .() ~ delete _; - - public this(uint8 level, StringView name) - { - Level = level; - Name.Set(name); - } - - public override void Compute(String input) - { - input.Append(scope $"{Name}"); - } -} \ No newline at end of file diff --git a/src/Sections/Paragraph.bf b/src/Sections/Paragraph.bf deleted file mode 100644 index 4ea1746..0000000 --- a/src/Sections/Paragraph.bf +++ /dev/null @@ -1,17 +0,0 @@ -namespace Writer.Sections; - -using System; - -class Paragraph : Section -{ - public override void Compute(System.String input) - { - String ipsum = """ - Lorem ipsum dolor sit amet consectetur adipiscing elit. Semper vel class aptent taciti sociosqu ad litora. Blandit quis suspendisse aliquet nisi sodales consequat magna. Cras eleifend turpis fames primis vulputate ornare sagittis. Sem placerat in id cursus mi pretium tellus. Orci varius natoque penatibus et magnis dis parturient. Finibus facilisis dapibus etiam interdum tortor ligula congue. Proin libero feugiat tristique accumsan maecenas potenti ultricies. Sed diam urna tempor pulvinar vivamus fringilla lacus. Eros lobortis nulla molestie mattis scelerisque maximus eget. Porta elementum a enim euismod quam justo lectus. Curabitur facilisi cubilia curae hac habitasse platea dictumst. Nisl malesuada lacinia integer nunc posuere ut hendrerit. Efficitur laoreet mauris pharetra vestibulum fusce dictum risus. Imperdiet mollis nullam volutpat porttitor ullamcorper rutrum gravida. Adipiscing elit quisque faucibus ex sapien vitae pellentesque. Ad litora torquent per conubia nostra inceptos himenaeos. Consequat magna ante condimentum neque at luctus nibh. Ornare sagittis vehicula praesent dui felis venenatis ultrices. Pretium tellus duis convallis tempus leo eu aenean. Dis parturient montes nascetur ridiculus mus donec rhoncus. Ligula congue sollicitudin erat viverra ac tincidunt nam. Potenti ultricies habitant morbi senectus netus suscipit auctor. Fringilla lacus nec metus bibendum egestas iaculis massa. Maximus eget fermentum odio phasellus non purus est. Justo lectus commodo augue arcu dignissim velit aliquam. Platea dictumst lorem ipsum dolor sit amet consectetur. Ut hendrerit semper vel class aptent taciti sociosqu. Dictum risus blandit quis suspendisse aliquet nisi sodales. Rutrum gravida cras eleifend turpis fames primis vulputate. Vitae pellentesque sem placerat in id cursus mi. Inceptos himenaeos orci varius natoque penatibus et magnis. Luctus nibh finibus facilisis dapibus etiam interdum tortor. Venenatis ultrices proin libero feugiat tristique accumsan maecenas. Eu aenean sed diam urna tempor pulvinar vivamus. Donec rhoncus eros lobortis nulla molestie mattis scelerisque. Tincidunt nam porta elementum a enim euismod quam. Suscipit auctor curabitur facilisi cubilia curae hac habitasse. Iaculis massa nisl malesuada lacinia integer nunc posuere. Purus est efficitur laoreet mauris pharetra vestibulum fusce. Velit aliquam imperdiet mollis nullam volutpat porttitor ullamcorper. Amet consectetur adipiscing elit quisque faucibus ex sapien. Taciti sociosqu ad litora torquent per conubia nostra. Nisi sodales consequat magna ante condimentum neque at. Primis vulputate ornare sagittis vehicula praesent dui felis. Cursus mi pretium tellus duis convallis tempus leo. Et magnis dis parturient montes nascetur ridiculus mus. Interdum tortor ligula congue sollicitudin erat viverra ac. Accumsan maecenas potenti ultricies habitant morbi senectus netus. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. - """; - - input.Append(scope $""" -

{ipsum}

- """); - } -} \ No newline at end of file diff --git a/src/TOCItem.bf b/src/TOCItem.bf new file mode 100644 index 0000000..94ab1a1 --- /dev/null +++ b/src/TOCItem.bf @@ -0,0 +1,19 @@ +namespace Writer; + +using System; +using System.Collections; + +struct TOCItem +{ + public StringView Name; + public StringView Page; + public Span Items; + + + public this(StringView name, StringView page, params Span items) + { + Name = name; + Page = page; + Items = items; + } +} \ No newline at end of file diff --git a/src/Writer.bf b/src/Writer.bf index ef18c55..4219bd7 100644 --- a/src/Writer.bf +++ b/src/Writer.bf @@ -6,60 +6,184 @@ using System.Collections; class Writer { - private List
_sections = new .() ~ DeleteContainerAndItems!(_); + private String _title = new .() ~ delete _; + private List _pages = new .() ~ delete _; - public String Title = new .("Writer page") ~ delete _; - - public String Style = new .(""" + public StringView DefaultStyle = """ @page { size:A4; margin-left:4cm; margin-right:2cm; margin-top:1.27cm; margin-bottom:2.5cm; + padding-top:0.5cm; + + @top-right { + content: counter(page); + font-size:10pt; + border-bottom:1px solid black; + margin-top:1.27cm; + height:0.5cm; + } + + @top-left { + font-size:10pt; + content: string(title); + border-bottom:1px solid black; + margin-top:1.27cm; + height:0.5cm; + } + @top-center { + border-bottom:1px solid black; + margin-top:1.27cm; + height:0.5cm; + } + + @footnote { + float: bottom; + border-top:1px solid black; + } + } + + @page cover { + + text-align:center; + break-after: page; + + @top-right { + content:none; + border-bottom:0px solid black; + } + @top-left { + content:none; + border-bottom:0px solid black; + } + @top-center { + border-bottom:0px solid black; + } + + } + @page index { + break-after: page; + + @top-right { + content: counter(page, upper-roman); + border-bottom:1px solid black; + } + + @top-left { + border-bottom:1px solid black; + } + @top-center { + border-bottom:1px solid black; + } + } + + @page image-index { + break-after: page; + + @top-right { + content: counter(page, upper-roman); + border-bottom:1px solid black; + } + + @top-left { + border-bottom:1px solid black; + } + @top-center { + border-bottom:1px solid black; + } + } + + @media screen { + .web { + max-width: 60rem; + margin: 0 auto; + } + .footnote { + display:none; + } } body { - margin:0px; - padding:0px; - line-height:150%; font-family:arial; font-size:12pt; } - h1, h2, h3, h4, h5, h6 { - border-bottom:1px solid black; - padding-bottom:5px; + h1, h2, h3 { + string-set: title content(text); } - """) ~ delete _; + code { + display:block; + border:1px solid black; + } + + .footnote { + float: footnote; + } + """; - public void Output(StringView location) + + + public this(StringView title = "Writer Document") { - String sections = new .(); - defer delete sections; + _title.Set(title); + } + ///Add a page to hte list of pages to render + public void Write(Page page) => _pages.Add(page); - File.WriteAllText(location, scope $""" - + ///Output the page into a html file + public Result Safe(StringView fileName = "index.html") + { + String pageContent = new .(); + defer delete pageContent; + String pageStyles = new .(); + defer delete pageStyles; + + pageStyles.Append(DefaultStyle); + int counter = 0; + for (var p in _pages) + { + counter++; + + p.ComputeStyle(scope $"class-{counter}", pageStyles); + pageContent.Append(scope $"
{p.ComputeContent(.. scope .())}
"); + } + + String output = new .(scope $""" + - - {Title} - - - - {this._ComputeSections(.. sections)} - - + + {_title} + + +
{pageContent}
"""); + defer delete output; + + if (File.WriteAllText(fileName, output) case .Err) + return .Err; + return .Ok; } - private void _ComputeSections(String buffer) + ///Convert the given html file into a pdf file, assuming pagedjs-cli is installed + public Result Convert(StringView inputFile, StringView fileName) { - for (var i in _sections) - i.Compute(buffer); + System.Diagnostics.ProcessStartInfo info = scope .(); + info.SetFileName("pagedjs-cli"); + //This might be vulnerable + info.SetArguments(scope $"{inputFile} -o {fileName}"); + + + System.Diagnostics.SpawnedProcess process = scope .(); + if (process.Start(info) case .Ok) + { + while (!process.HasExited) + continue; + return .Ok; + } + + return .Err; } - - - public void AddHeading(uint8 size, StringView content) => _sections.Add(new Writer.Sections.Heading(size, content)); - public void AddParagraph() => _sections.Add(new Writer.Sections.Paragraph()); } \ No newline at end of file