| 465 | 465 | const styleDecodeRegex = /<custom-style>(.+?)<\/custom-style>/gms; |
| 466 | 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 | 507 | return text.replaceAll(styleDecodeRegex, (_, style) => { |
| 469 | 508 | try { |
| 470 | 509 | let styleCleaned = unescape(style).replaceAll(/<br\/>/g, ''); |
| 471 | 510 | const ast = css.parse(styleCleaned); |
| 472 | 511 | const rulessheet = ast?.stylesheet?.rules; |
| 473 | 512 | if (rulessheet) { |
| 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 | 515 | return `<style>${css.stringify(ast)}</style>`; |
| 506 | 516 | } catch (error) { |