Skip to content

Commit

Permalink
Books now render Markdown, fixing paper importing (tgstation#74902)
Browse files Browse the repository at this point in the history
## About The Pull Request

Books didn't render markdown and instead just dumped the raw contents,
(after a html encode), into the window.
Changes them to use tgui and support markdown rendering.
## Why It's Good For The Game

Books should should look the same as the paper used to make them.
## Changelog
:cl:
fix: Book's no longer take your formatting and throw it out the window.
refactor: Book display and rendering
/:cl:

---------

Co-authored-by: GoldenAlpharex <[email protected]>
Co-authored-by: Mothblocks <[email protected]>
  • Loading branch information
3 people authored Apr 25, 2023
1 parent 88cb28b commit 548fc4a
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 18 deletions.
3 changes: 0 additions & 3 deletions code/modules/fishing/fish_catalog.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
icon_state = "fishbook"
starting_content = "Lot of fish stuff" //book wrappers could use cleaning so this is not necessary

/obj/item/book/fish_catalog/on_read(mob/user)
ui_interact(user)

/obj/item/book/fish_catalog/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
Expand Down
41 changes: 27 additions & 14 deletions code/modules/library/book.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@
var/raw_content = ""

for(var/datum/paper_input/text_input as anything in paper.raw_text_inputs)
raw_content += text_input.raw_text

// Content from paper is never trusted. It it raw, unsanitised, unparsed user input.
if(!isnull(text_input.colour))
raw_content += text_input.raw_text
else
raw_content += "<font color='[text_input.colour]'>[text_input.raw_text]</font>"
content = trim(html_encode(raw_content), MAX_PAPER_LENGTH)

/datum/book_info/proc/get_content(default="N/A")
Expand Down Expand Up @@ -112,19 +113,29 @@

AddElement(/datum/element/falling_hazard, damage = 5, wound_bonus = 0, hardhat_safety = TRUE, crushes = FALSE, impact_sound = drop_sound)

/obj/item/book/proc/on_read(mob/living/user)
if(book_data?.content)
user << browse("<meta charset=UTF-8><TT><I>Penned by [book_data.author].</I></TT> <BR>" + "[book_data.content]", "window=book[window_size != null ? ";size=[window_size]" : ""]")
/obj/item/book/ui_static_data(mob/user)
var/list/data = list()
data["author"] = book_data.get_author()
data["title"] = book_data.get_title()
data["content"] = book_data.get_content()
return data

LAZYINITLIST(user.mind?.book_titles_read)
var/has_not_read_book = isnull(user.mind?.book_titles_read[starting_title])
/obj/item/book/ui_interact(mob/living/user, datum/tgui/ui)
if(!length(book_data.get_content()))
balloon_alert(user, "this book is blank!")
return

if(has_not_read_book) // any new books give bonus mood
if(istype(user) && !isnull(user.mind))
LAZYINITLIST(user.mind.book_titles_read)
var/has_not_read_book = !(starting_title in user.mind.book_titles_read)
if(has_not_read_book)
user.add_mood_event("book_nerd", /datum/mood_event/book_nerd)
user.mind?.book_titles_read[starting_title] = TRUE
onclose(user, "book")
else
to_chat(user, span_notice("This book is completely blank!"))
user.mind.book_titles_read[starting_title] = TRUE

ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MarkdownViewer", name)
ui.open()

/// Generates a random icon state for the book
/obj/item/book/proc/gen_random_icon_state()
Expand All @@ -134,10 +145,12 @@
if(user.is_blind())
to_chat(user, span_warning("You are blind and can't read anything!"))
return

if(!user.can_read(src))
return

user.visible_message(span_notice("[user] opens a book titled \"[book_data.title]\" and begins reading intently."))
on_read(user)
ui_interact(user)

/obj/item/book/attackby(obj/item/attacking_item, mob/user, params)
if(burn_paper_product_attackby_check(attacking_item, user))
Expand Down
27 changes: 26 additions & 1 deletion code/modules/library/lib_machines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,13 @@
icon_state = "binder"
desc = "Only intended for binding paper products."
density = TRUE

/// Are we currently binding a book?
var/busy = FALSE

/// Name of the author for the book, set by scanning your ID.
var/scanned_name

/obj/machinery/bookbinder/wrench_act(mob/living/user, obj/item/tool)
. = ..()
default_unfasten_wrench(user, tool)
Expand All @@ -786,17 +791,32 @@
/obj/machinery/bookbinder/attackby(obj/hitby, mob/user, params)
if(istype(hitby, /obj/item/paper))
prebind_book(user, hitby)
return
return TRUE

if(isidcard(hitby))
var/obj/item/card/id/idcard = hitby
scanned_name = idcard.registered_name
balloon_alert(user, "scanned")
return TRUE

return ..()

/obj/machinery/bookbinder/proc/prebind_book(mob/user, obj/item/paper/draw_from)
if(machine_stat)
return

if(busy)
to_chat(user, span_warning("The book binder is busy. Please wait for completion of previous operation."))
return

if(!scanned_name)
scanned_name = "unknown author"
say("No ID detected. Please scan your ID if you would like to be credited for this book. Otherwise please enter your paper again.")
return

if(!user.transferItemToLoc(draw_from, src))
return

user.visible_message(span_notice("[user] loads some paper into [src]."), span_notice("You load some paper into [src]."))
audible_message(span_hear("[src] begins to hum as it warms up its printing drums."))
busy = TRUE
Expand All @@ -808,14 +828,19 @@
busy = FALSE
if(!draw_from) //What the fuck did you do
return

if(machine_stat)
draw_from.forceMove(drop_location())
return

visible_message(span_notice("[src] whirs as it prints and binds a new book."))
var/obj/item/book/bound_book = new(loc)
bound_book.book_data.set_content_using_paper(draw_from)
bound_book.book_data.set_author(scanned_name, trusted = FALSE)
bound_book.name = "Print Job #" + "[rand(100, 999)]"
bound_book.gen_random_icon_state()
scanned_name = null

qdel(draw_from)

#undef BOOKS_PER_PAGE
Expand Down
42 changes: 42 additions & 0 deletions tgui/packages/tgui/interfaces/MarkdownViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { marked } from 'marked';
import { useBackend } from '../backend';
import { Window } from '../layouts';
import { sanitizeText } from '../sanitize';

type MarkdownViewerData = {
title: string;
content: string;
author: string;
};

export const MarkdownViewer = (_: any, context: any) => {
const { data } = useBackend<MarkdownViewerData>(context);
return (
<Window theme="paper" title={data.title}>
<Window.Content scrollable backgroundColor={'#FFFFFF'}>
<MarkdownRenderer content={data.content} />
</Window.Content>
</Window>
);
};

type MarkdownRendererProps = {
content: string;
sanitize?: boolean;
};

export const MarkdownRenderer = (props: MarkdownRendererProps) => {
let { content, sanitize } = props;

content = marked(content);
if (sanitize) {
content = sanitizeText(content, /* advHtml = */ false);
}

// eslint-disable-next-line react/no-danger
return <div dangerouslySetInnerHTML={{ __html: content }} />;
};

MarkdownRenderer.defaultProps = {
sanitize: true,
};

0 comments on commit 548fc4a

Please sign in to comment.