diff --git a/src/ts/parser.ts b/src/ts/parser.ts index 29b486d6..af081bae 100644 --- a/src/ts/parser.ts +++ b/src/ts/parser.ts @@ -42,34 +42,17 @@ DOMPurify.addHook("uponSanitizeElement", (node: HTMLElement, data) => { return node.parentNode.removeChild(node); } } - if(data.tagName === 'style'){ - try { - const ast = css.parse(node.innerHTML) - const rules = ast?.stylesheet?.rules - if(rules){ - for(const rule of rules){ - if(rule.selectors){ - for(let i=0;i { if(data.attrName === 'style'){ data.attrValue = data.attrValue.replace(/(absolute)|(z-index)|(fixed)/g, '') } + if(data.attrName === 'class'){ + data.attrValue = data.attrValue.split(' ').map((v) => { + return "x-risu-" + v + }).join(' ') + } }) async function parseAdditionalAssets(data:string, char:character, mode:'normal'|'back'){ @@ -102,17 +85,57 @@ export async function ParseMarkdown(data:string, char:(character | groupChat) = if(firstParsed !== data && char && char.type !== 'group'){ data = await parseAdditionalAssets(data, char, mode) } - return DOMPurify.sanitize(mconverted.parse(data), { - ADD_TAGS: ["iframe"], + return decodeStyle(DOMPurify.sanitize(mconverted.parse(encodeStyle(data)), { + ADD_TAGS: ["iframe", "style", "risu-style"], ADD_ATTR: ["allow", "allowfullscreen", "frameborder", "scrolling"], FORBID_ATTR: ["href"] - }) + })) } export function parseMarkdownSafe(data:string) { return DOMPurify.sanitize(safeConvertor.makeHtml(data), { FORBID_TAGS: ["a", "style"], - FORBID_ATTR: ["style", "href"] + FORBID_ATTR: ["style", "href", "class"] + }) +} + + +const styleRegex = /\(.+?)\<\/style\>/gms +function encodeStyle(txt:string){ + return txt.replaceAll(styleRegex, (f, c1) => { + return "" + Buffer.from(c1).toString('hex') + "" + }) +} +const styleDecodeRegex = /\(.+?)\<\/risu-style\>/gms + +function decodeStyle(text:string){ + + return text.replaceAll(styleDecodeRegex, (full, txt:string) => { + try { + const ast = css.parse(Buffer.from(txt, 'hex').toString('utf-8')) + const rules = ast?.stylesheet?.rules + if(rules){ + for(const rule of rules){ + if(rule.selectors){ + for(let i=0;i { + if(v.startsWith('.')){ + return ".x-risu-" + v.substring(1) + } + return v + }).join(' ') + + rule.selectors[i] = ".chattext " + selectors + } + } + } + } + return `` + + } catch (error) { + return `CSS ERROR: ${error}`; + } }) } diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts index bad28ec2..71278e09 100644 --- a/src/ts/storage/database.ts +++ b/src/ts/storage/database.ts @@ -363,6 +363,7 @@ export interface character{ replaceGlobalNote:string backgroundHTML?:string reloadKeys?:number + backgroundCSS?:string } @@ -401,6 +402,7 @@ export interface groupChat{ orderByOrder?:boolean backgroundHTML?:string, reloadKeys?:number + backgroundCSS?:string } export interface botPreset{