diff --git a/tgui/packages/tgui/interfaces/MarkdownViewer.tsx b/tgui/packages/tgui/interfaces/MarkdownViewer.tsx index 9ee7764f9ed..092c68d8735 100644 --- a/tgui/packages/tgui/interfaces/MarkdownViewer.tsx +++ b/tgui/packages/tgui/interfaces/MarkdownViewer.tsx @@ -29,7 +29,7 @@ type MarkdownRendererProps = { export const MarkdownRenderer = (props: MarkdownRendererProps) => { let { content, sanitize } = props; - content = marked(content); + content = marked(content, { async: false }); if (sanitize) { content = sanitizeText(content, /* advHtml = */ false); } diff --git a/tgui/packages/tgui/interfaces/PaperSheet/Preview.tsx b/tgui/packages/tgui/interfaces/PaperSheet/Preview.tsx index 5f3229a2d08..fdcc3671116 100644 --- a/tgui/packages/tgui/interfaces/PaperSheet/Preview.tsx +++ b/tgui/packages/tgui/interfaces/PaperSheet/Preview.tsx @@ -1,10 +1,12 @@ import { marked } from 'marked'; +import { baseUrl } from 'marked-base-url'; +import { markedSmartypants } from 'marked-smartypants'; import { Component, RefObject } from 'react'; import { Box, Section } from 'tgui-core/components'; import { useBackend, useLocalState } from '../../backend'; import { sanitizeText } from '../../sanitize'; -import { canEdit, tokenizer, walkTokens } from './helpers'; +import { tokenizer, walkTokens } from './helpers'; import { StampView } from './StampView'; import { FieldInput, InteractionType, PaperContext } from './types'; @@ -12,6 +14,7 @@ type PreviewViewProps = { scrollableRef: RefObject; handleOnScroll: (this: GlobalEventHandlers, ev: Event) => any; textArea: string; + canEdit: boolean; }; type FieldCreationReturn = { @@ -78,15 +81,17 @@ export class PreviewView extends Component { walkTokens, }; - marked.use({ - extensions: [inputField], - breaks: true, - gfm: true, - smartypants: true, - walkTokens: walkTokens, + marked.use( + { + extensions: [inputField], + breaks: true, + gfm: true, + walkTokens: walkTokens, + }, + markedSmartypants(), // Once assets are fixed might need to change this for them - baseUrl: 'thisshouldbreakhttp', - }); + baseUrl('thisshouldbreakhttp'), + ); }; // Extracts the paper field "counter" from a full ID. @@ -145,6 +150,12 @@ export class PreviewView extends Component { document.removeEventListener('input', this.onInputHandler); } + shouldComponentUpdate(nextProps: Readonly): boolean { + if (!this.props.canEdit) return true; + + return this.props.canEdit !== nextProps.canEdit; + } + // Creates the partial inline HTML for previewing or reading the paper from // only static_ui_data from DM. createPreviewFromDM = (): { text: string; newFieldCount: number } => { @@ -155,13 +166,12 @@ export class PreviewView extends Component { default_pen_font, default_pen_color, paper_color, - held_item_details, } = data; let output = ''; let fieldCount = 0; - const readOnly = !canEdit(held_item_details); + const readOnly = !this.props.canEdit; // If readonly is the same (input field writiability state hasn't changed) // And the input stats are the same (no new text inputs since last time) @@ -254,7 +264,7 @@ export class PreviewView extends Component { text: string, font: string, color: string, - bold: boolean = false, + bold = false, ): string => { return ` { - const textHtml = { - __html: sanitizeText( - marked(value, { +type ProcessedText = { + __html: string; +}; + +export function processedText(value: string | null): ProcessedText { + if (!value) { + return { __html: '' }; + } + + const parsed = marked + .use( + { breaks: true, - smartypants: true, - smartLists: true, - baseUrl: 'thisshouldbreakhttp', - }), - ), + }, + markedSmartypants(), + baseUrl('thisshouldbreakhttp'), + ) + .parse(value, { async: false }); + + const textHtml = { + __html: sanitizeText(parsed), }; return textHtml; -}; +} diff --git a/tgui/yarn.lock b/tgui/yarn.lock index 5aa9d58c57a..ba48dbcf689 100644 --- a/tgui/yarn.lock +++ b/tgui/yarn.lock @@ -3918,13 +3918,6 @@ __metadata: languageName: node linkType: hard -"@types/marked@npm:4.3.2": - version: 4.3.2 - resolution: "@types/marked@npm:4.3.2" - checksum: 10c0/6f44d28da5c940a719d6c6aca41e33f49c5fe957f7972939cc1cbb47d045951f4d969f382d655345d0463e47db1994635d2862018716fcef2fa85ceeceb116e7 - languageName: node - linkType: hard - "@types/mime@npm:^1": version: 1.3.5 resolution: "@types/mime@npm:1.3.5" @@ -13824,12 +13817,32 @@ __metadata: languageName: node linkType: hard -"marked@npm:^4.3.0": - version: 4.3.0 - resolution: "marked@npm:4.3.0" +"marked-base-url@npm:^1.1.6": + version: 1.1.6 + resolution: "marked-base-url@npm:1.1.6" + peerDependencies: + marked: ">= 4 < 16" + checksum: 10c0/346b8f3a912ab5192caec896d8e923b83113f81312eb4838ec9773aca620088cd3ed4d9fce773f3251d71c72f271c3df8554f025c1146cea3e76845b29e5be42 + languageName: node + linkType: hard + +"marked-smartypants@npm:^1.1.9": + version: 1.1.9 + resolution: "marked-smartypants@npm:1.1.9" + dependencies: + smartypants: "npm:^0.2.2" + peerDependencies: + marked: ">=4 <16" + checksum: 10c0/50a9f9ddeb67045933c26abdd8acf997368d96920990048b6d432c4d2374a513152c639b46c16c74934483b7a1df6093f8f26461f2409b9bf1e58f8ac759391f + languageName: node + linkType: hard + +"marked@npm:^15.0.11": + version: 15.0.11 + resolution: "marked@npm:15.0.11" bin: marked: bin/marked.js - checksum: 10c0/0013463855e31b9c88d8bb2891a611d10ef1dc79f2e3cbff1bf71ba389e04c5971298c886af0be799d7fa9aa4593b086a136062d59f1210b0480b026a8c5dc47 + checksum: 10c0/d532db4955c1f2ac6efc65a644725e9e12e7944cb6af40c7148baecfd3b3c2f3564229b3daf12d2125635466448fb9b367ce52357be3aea0273e3d152efdbdcf languageName: node linkType: hard @@ -18699,6 +18712,16 @@ __metadata: languageName: node linkType: hard +"smartypants@npm:^0.2.2": + version: 0.2.2 + resolution: "smartypants@npm:0.2.2" + bin: + smartypants: bin/smartypants.js + smartypantsu: bin/smartypantsu.js + checksum: 10c0/29b46df6acaed9ad6271624e26e055d6360c9da7f79433b7a83ebd40b50bd6b554d8f3793932f42be07e5badce889f547c89378fda77cb1f935b09a902c4527b + languageName: node + linkType: hard + "snake-case@npm:^3.0.4": version: 3.0.4 resolution: "snake-case@npm:3.0.4" @@ -19885,7 +19908,6 @@ __metadata: version: 0.0.0-use.local resolution: "tgui@workspace:packages/tgui" dependencies: - "@types/marked": "npm:4.3.2" "@types/react": "npm:^19.1.0" "@types/react-dom": "npm:^19.1.2" common: "workspace:*" @@ -19895,7 +19917,9 @@ __metadata: highlight.js: "npm:^11.11.1" jest: "npm:^29.7.0" js-yaml: "npm:^4.1.0" - marked: "npm:^4.3.0" + marked: "npm:^15.0.11" + marked-base-url: "npm:^1.1.6" + marked-smartypants: "npm:^1.1.9" react: "npm:^19.1.0" react-dom: "npm:^19.1.0" tgui-core: "npm:^3.1.4"