diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFormatter.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFormatter.java
new file mode 100644
index 0000000..50f0f9b
--- /dev/null
+++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFormatter.java
@@ -0,0 +1,92 @@
+package net.knarcraft.bookswithoutborders.utility;
+
+import java.util.List;
+
+/**
+ * A class for formatting text to fit books
+ *
+ *
The book formatter
+ */
+public class BookFormatter {
+
+ /**
+ * Formats the last page of a set of pages
+ *
+ * If the last page is non-empty and has space, a newline is added. If the last two pages' contents can fit on
+ * the same page, they will be combined.
+ *
+ * @param rawPages A list of pages
+ */
+ public static void formatLastPage(List rawPages) {
+ int maxPageText = 256;
+ int fitsNewline = maxPageText - 2;
+
+ //Adds newline if the contents of the last page does not exceed page limit and is non-empty
+ formatLastPageAddNewline(rawPages, fitsNewline);
+
+ //Combines the two last pages if they can fit on one page
+ if (rawPages.size() > 1) {
+ formatLastPageCombinePages(rawPages, maxPageText);
+ }
+
+ //Splits the last page if it is too long
+ if (rawPages.get(rawPages.size() - 1).length() > maxPageText) {
+ formatLastPageSplitOverflow(rawPages, maxPageText, fitsNewline);
+ }
+ }
+
+ /**
+ * Splits the last page if it overflows
+ * @param rawPages The raw pages to format
+ * @param maxPageText The max number of characters which fit on a page
+ * @param fitsNewline The max number of characters on a page which still fits a newline character
+ */
+ public static void formatLastPageSplitOverflow(List rawPages, int maxPageText, int fitsNewline) {
+ while (rawPages.get(rawPages.size() - 1).length() > maxPageText) {
+ int splitPosition;
+ String fittingText = rawPages.get(rawPages.size() - 1).substring(0, maxPageText);
+ int lastSpaceBeforePageBreak = fittingText.lastIndexOf(" ");
+
+ if (lastSpaceBeforePageBreak > -1) {
+ //Split at space if it exists
+ rawPages.add(rawPages.get(rawPages.size() - 1).substring(lastSpaceBeforePageBreak + 1));
+ splitPosition = lastSpaceBeforePageBreak;
+ } else {
+ //Split at text limit
+ rawPages.add(rawPages.get(rawPages.size() - 1).substring(maxPageText));
+ splitPosition = maxPageText;
+ }
+ //Adds newline if the contents of the last page does not exceed page limit and is non-empty
+ formatLastPageAddNewline(rawPages, fitsNewline);
+ //Removes excess page content
+ rawPages.set(rawPages.size() - 2, rawPages.get(rawPages.size() - 2).substring(0, splitPosition));
+ }
+ }
+
+ /**
+ * Combines the two last pages if they can fit on the same page
+ * @param rawPages The raw pages to format
+ * @param maxPageText The max number of characters which fit on a page
+ */
+ public static void formatLastPageCombinePages(List rawPages, int maxPageText) {
+ int lastPageIndex = rawPages.size() - 1;
+ int nextToLastIndex = rawPages.size() - 2;
+ if (rawPages.get(nextToLastIndex).length() + rawPages.get(lastPageIndex).length() <= maxPageText) {
+ rawPages.set(nextToLastIndex, (rawPages.get(nextToLastIndex)) + (rawPages.get(lastPageIndex)));
+ rawPages.remove(lastPageIndex);
+ }
+ }
+
+ /**
+ * Adds newline if the contents of the last page does not exceed page limit and is non-empty
+ * @param rawPages The raw pages to format
+ * @param fitsNewline The max number of characters on a page which still fits a newline character
+ */
+ public static void formatLastPageAddNewline(List rawPages, int fitsNewline) {
+ int pageIndex = rawPages.size() - 1;
+ if (rawPages.get(pageIndex).length() <= fitsNewline && !rawPages.get(pageIndex).isEmpty()) {
+ rawPages.set(pageIndex, (rawPages.get(pageIndex)) + "\n");
+ }
+ }
+
+}