diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 1688bd2ba828a..ac6dce638353f 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -75,9 +75,12 @@
if(!GLOB.station_goals.len)
return
. = "
Special Orders for [station_name()]:
"
+ var/list/goal_reports = list()
for(var/datum/station_goal/station_goal as anything in GLOB.station_goals)
station_goal.on_report()
- . += station_goal.get_report()
+ goal_reports += station_goal.get_report()
+
+ . += goal_reports.Join("
")
return
/*
diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm
index e675378ceb82a..492ec97f31d47 100644
--- a/code/modules/station_goals/bsa.dm
+++ b/code/modules/station_goals/bsa.dm
@@ -10,11 +10,13 @@ GLOBAL_VAR_INIT(bsa_unlock, FALSE)
name = "Bluespace Artillery"
/datum/station_goal/bluespace_cannon/get_report()
- return {"Our military presence is inadequate in your sector.
- We need you to construct BSA-[rand(1,99)] Artillery position aboard your station.
-
- Base parts are available for shipping via cargo.
- -Nanotrasen Naval Command"}
+ return list(
+ "Our military presence is inadequate in your sector.",
+ "We need you to construct BSA-[rand(1,99)] Artillery position aboard your station.",
+ "",
+ "Base parts are available for shipping via cargo.",
+ "-Nanotrasen Naval Command
",
+ ).Join("\n")
/datum/station_goal/bluespace_cannon/on_report()
//Unlock BSA parts
diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm
index ca0bb510b1511..4166463fb6b86 100644
--- a/code/modules/station_goals/dna_vault.dm
+++ b/code/modules/station_goals/dna_vault.dm
@@ -32,15 +32,17 @@
.++
/datum/station_goal/dna_vault/get_report()
- return {"Our long term prediction systems indicate a 99% chance of system-wide cataclysm in the near future.
- We need you to construct a DNA Vault aboard your station.
-
- The DNA Vault needs to contain samples of:
- [animal_count] unique animal data
- [plant_count] unique non-standard plant data
- [human_count] unique sapient humanoid DNA data
-
- Base vault parts are available for shipping via cargo."}
+ return list(
+ "Our long term prediction systems indicate a 99% chance of system-wide cataclysm in the near future.",
+ "We need you to construct a DNA Vault aboard your station.",
+ "",
+ "The DNA Vault needs to contain samples of:",
+ "* [animal_count] unique animal data",
+ "* [plant_count] unique non-standard plant data",
+ "* [human_count] unique sapient humanoid DNA data",
+ "",
+ "Base vault parts are available for shipping via cargo.
",
+ ).Join("\n")
/datum/station_goal/dna_vault/on_report()
diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm
index 058606f1ac88e..16dc79bf05ac8 100644
--- a/code/modules/station_goals/shield.dm
+++ b/code/modules/station_goals/shield.dm
@@ -7,11 +7,12 @@
requires_space = TRUE
/datum/station_goal/station_shield/get_report()
- return {"The station is located in a zone full of space debris.
- We have a prototype shielding system you must deploy to reduce collision-related accidents.
-
- You can order the satellites and control systems at cargo.
- "}
+ return list(
+ "The station is located in a zone full of space debris.",
+ "We have a prototype shielding system you must deploy to reduce collision-related accidents.",
+ "",
+ "You can order the satellites and control systems at cargo.
",
+ ).Join("\n")
/datum/station_goal/station_shield/on_report()
diff --git a/tgui/packages/tgui/interfaces/PaperSheet.tsx b/tgui/packages/tgui/interfaces/PaperSheet.tsx
index d89cea97151a0..55e31d63806df 100644
--- a/tgui/packages/tgui/interfaces/PaperSheet.tsx
+++ b/tgui/packages/tgui/interfaces/PaperSheet.tsx
@@ -591,7 +591,43 @@ export class PreviewView extends Component {
break;
}
};
- return marked(rawText, {
+
+ // This is an extension for marked defining a complete custom tokenizer.
+ // This tokenizer should run before the the non-custom ones, and gives us
+ // the ability to handle [_____] fields before the em/strong tokenizers
+ // mangle them, since underscores are used for italic/bold.
+ // This massively improves the order of operations, allowing us to run
+ // marked, THEN sanitise the output (much safer) and finally insert fields
+ // manually afterwards.
+ const inputField = {
+ name: 'inputField',
+ level: 'inline',
+
+ start(src) {
+ return src.match(/\[/)?.index;
+ },
+
+ tokenizer(src: string) {
+ const rule = /^\[_+\]/;
+ const match = src.match(rule);
+ if (match) {
+ const token = {
+ type: 'inputField',
+ raw: match[0],
+ };
+ return token;
+ }
+ },
+
+ renderer(token) {
+ return `${token.raw}`;
+ },
+ };
+
+ // marked.use({ tokenizer });
+ marked.use({ extensions: [inputField] });
+
+ return marked.parse(rawText, {
breaks: true,
smartypants: true,
smartLists: true,
@@ -615,10 +651,13 @@ export class PreviewView extends Component {
// First lets make sure it ends in a new line
rawText += rawText[rawText.length] === '\n' ? '\n' : '\n\n';
- // Second, we sanitize the text of html
- const sanitizedText = sanitizeText(rawText);
+ // Second, parse the text using markup
+ const parsedText = this.runMarkedDefault(rawText);
- // Third we replace the [__] with fields as markedjs fucks them up
+ // Third, we sanitize the text of html
+ const sanitizedText = sanitizeText(parsedText);
+
+ // Fourth we replace the [__] with fields
const fieldedText = this.createFields(
sanitizedText,
font,
@@ -629,11 +668,8 @@ export class PreviewView extends Component {
fieldCounter
);
- // Fourth, parse the text using markup
- const parsedText = this.runMarkedDefault(fieldedText.text);
-
// Fifth, we wrap the created text in the writing implement properties.
- const fontedText = this.setFontInText(parsedText, font, color, bold);
+ const fontedText = this.setFontInText(fieldedText.text, font, color, bold);
return { text: fontedText, nextCounter: fieldedText.nextCounter };
};
diff --git a/tgui/packages/tgui/sanitize.js b/tgui/packages/tgui/sanitize.js
index de671f376aad3..fded31088d37b 100644
--- a/tgui/packages/tgui/sanitize.js
+++ b/tgui/packages/tgui/sanitize.js
@@ -7,6 +7,7 @@ import DOMPurify from 'dompurify';
// Default values
const defTag = [
'b',
+ 'blockquote',
'br',
'center',
'code',