| 465 | const styleDecodeRegex = /<custom-style>(.+?)<\/custom-style>/gms; | 465 | const styleDecodeRegex = /<custom-style>(.+?)<\/custom-style>/gms; |
| 466 | const mediaAllowed = isExternalMediaAllowed(); | 466 | const mediaAllowed = isExternalMediaAllowed(); |
| 467 | | 467 | |
| | 468 | function sanitizeRule(rule) { |
| | 469 | if (rule.selectors) { |
| | 470 | for (let i = 0; i < rule.selectors.length; i++) { |
| | 471 | let selector = rule.selectors[i]; |
| | 472 | if (selector) { |
| | 473 | let selectors = (selector.split(' ') ?? []).map((v) => { |
| | 474 | if (v.startsWith('.')) { |
| | 475 | return '.custom-' + v.substring(1); |
| | 476 | } |
| | 477 | return v; |
| | 478 | }).join(' '); |
| | 479 | |
| | 480 | rule.selectors[i] = '.mes_text ' + selectors; |
| | 481 | } |
| | 482 | } |
| | 483 | } |
| | 484 | if (!mediaAllowed && Array.isArray(rule.declarations) && rule.declarations.length > 0) { |
| | 485 | for (const declaration of rule.declarations) { |
| | 486 | if (declaration.value.includes('://')) { |
| | 487 | rule.declarations.splice(rule.declarations.indexOf(declaration), 1); |
| | 488 | } |
| | 489 | } |
| | 490 | } |
| | 491 | } |
| | 492 | |
| | 493 | function sanitizeRuleSet(ruleSet) { |
| | 494 | if (ruleSet.type === 'rule') { |
| | 495 | sanitizeRule(ruleSet); |
| | 496 | } |
| | 497 | |
| | 498 | if (Array.isArray(ruleSet.rules)) { |
| | 499 | ruleSet.rules = ruleSet.rules.filter(rule => rule.type !== 'import'); |
| | 500 | |
| | 501 | for (const mediaRule of ruleSet.rules) { |
| | 502 | sanitizeRuleSet(mediaRule); |
| | 503 | } |
| | 504 | } |
| | 505 | } |
| | 506 | |
| 468 | return text.replaceAll(styleDecodeRegex, (_, style) => { | 507 | return text.replaceAll(styleDecodeRegex, (_, style) => { |
| 469 | try { | 508 | try { |
| 470 | let styleCleaned = unescape(style).replaceAll(/<br\/>/g, ''); | 509 | let styleCleaned = unescape(style).replaceAll(/<br\/>/g, ''); |
| 471 | const ast = css.parse(styleCleaned); | 510 | const ast = css.parse(styleCleaned); |
| 472 | const rules = ast?.stylesheet?.rules; | 511 | const sheet = ast?.stylesheet; |
| 473 | if (rules) { | 512 | if (sheet) { |
| 474 | for (const rule of rules) { | 513 | sanitizeRuleSet(ast.stylesheet); |
| 475 | if (rule.type === 'import') { | | |
| 476 | rules.splice(rules.indexOf(rule), 1); | | |
| 477 | } | | |
| 478 | | | |
| 479 | if (rule.type === 'rule') { | | |
| 480 | if (rule.selectors) { | | |
| 481 | for (let i = 0; i < rule.selectors.length; i++) { | | |
| 482 | let selector = rule.selectors[i]; | | |
| 483 | if (selector) { | | |
| 484 | let selectors = (selector.split(' ') ?? []).map((v) => { | | |
| 485 | if (v.startsWith('.')) { | | |
| 486 | return '.custom-' + v.substring(1); | | |
| 487 | } | | |
| 488 | return v; | | |
| 489 | }).join(' '); | | |
| 490 | | | |
| 491 | rule.selectors[i] = '.mes_text ' + selectors; | | |
| 492 | } | | |
| 493 | } | | |
| 494 | } | | |
| 495 | if (!mediaAllowed && Array.isArray(rule.declarations) && rule.declarations.length > 0) { | | |
| 496 | for (const declaration of rule.declarations) { | | |
| 497 | if (declaration.value.includes('://')) { | | |
| 498 | rule.declarations.splice(rule.declarations.indexOf(declaration), 1); | | |
| 499 | } | | |
| 500 | } | | |
| 501 | } | | |
| 502 | } | | |
| 503 | } | | |
| 504 | } | 514 | } |
| 505 | return `<style>${css.stringify(ast)}</style>`; | 515 | return `<style>${css.stringify(ast)}</style>`; |
| 506 | } catch (error) { | 516 | } catch (error) { |