1
0

Verbessere Country Flag Fixer

This commit is contained in:
Akamaru
2025-10-12 16:02:56 +02:00
parent c929075fab
commit 36ae2acc3d

View File

@@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name Country Flag Fixer // @name Country Flag Fixer
// @namespace https://git.ponywave.de/Akamaru/Userscripts // @namespace https://git.ponywave.de/Akamaru/Userscripts
// @version 1.0 // @version 1.1
// @description Ersetzt Ländercodes mit echten Flaggen-Emojis unter Windows/Chromium // @description Ersetzt Ländercodes mit echten Flaggen-Emojis unter Windows/Chromium
// @author Akamaru // @author Akamaru
// @match *://*/* // @match *://*/*
@@ -12,7 +12,6 @@
// @run-at document-start // @run-at document-start
// ==/UserScript== // ==/UserScript==
// Source: https://github.com/talkjs/country-flag-emoji-polyfill
(function() { (function() {
'use strict'; 'use strict';
@@ -20,16 +19,12 @@
const extentionStyleTagId = "country-flag-fixer-ext"; const extentionStyleTagId = "country-flag-fixer-ext";
const headStyleTagId = "country-flag-fixer-ext-head"; const headStyleTagId = "country-flag-fixer-ext-head";
/**
* Registriere die Custom Font-Face für Flaggen-Emojis
*/
const loadFontFace = () => { const loadFontFace = () => {
const fontUrl = GM_getResourceURL('TwemojiCountryFlags'); const fontUrl = GM_getResourceURL('TwemojiCountryFlags');
const style = document.createElement("style"); const style = document.createElement("style");
style.setAttribute("type", "text/css"); style.setAttribute("type", "text/css");
style.setAttribute("id", headStyleTagId); style.setAttribute("id", headStyleTagId);
// Unicode range generiert von: https://wakamaifondue.com/beta/
style.textContent = ` style.textContent = `
@font-face { @font-face {
font-family: "${replacementFontName}"; font-family: "${replacementFontName}";
@@ -40,50 +35,39 @@
@font-face { @font-face {
font-family: "${replacementFontName}"; font-family: "${replacementFontName}";
font-style: italic; /* Verhindert kursive Flaggen */ font-style: italic;
src: url('${fontUrl}') format('woff2'); src: url('${fontUrl}') format('woff2');
unicode-range: U+1F1E6-1F1FF, U+1F3F4, U+E0062-E0063, U+E0065, U+E0067, U+E006C, U+E006E, U+E0073-E0074, U+E0077, U+E007F; unicode-range: U+1F1E6-1F1FF, U+1F3F4, U+E0062-E0063, U+E0065, U+E0067, U+E006C, U+E006E, U+E0073-E0074, U+E0077, U+E007F;
} }
`; `;
// Prüfe auf Fälle wie SVG-Dateien ohne head-Element
if (document.head != undefined) { if (document.head != undefined) {
document.head.appendChild(style); document.head.appendChild(style);
} }
}; };
/**
* Extrahiere font-family Regeln aus allen Stylesheets
*/
const extractFontFamilyRules = () => { const extractFontFamilyRules = () => {
const fontFamilyRules = []; const fontFamilyRules = [];
for (const sheet of document.styleSheets) { for (const sheet of document.styleSheets) {
// Ignoriere Styles von dieser Extension
if (sheet.ownerNode?.id == extentionStyleTagId || sheet.ownerNode?.id == headStyleTagId) if (sheet.ownerNode?.id == extentionStyleTagId || sheet.ownerNode?.id == headStyleTagId)
continue; continue;
// Ignoriere non-screen Stylesheets
const sheetMediaBlacklist = ['print', 'speech', 'aural', 'braille', 'handheld', 'projection', 'tty']; const sheetMediaBlacklist = ['print', 'speech', 'aural', 'braille', 'handheld', 'projection', 'tty'];
if (sheetMediaBlacklist.includes(sheet.media.mediaText)) if (sheetMediaBlacklist.includes(sheet.media.mediaText))
continue; continue;
try { try {
// Loop durch jeden CSS-Selektor im Stylesheet
for (const rule of sheet.cssRules) { for (const rule of sheet.cssRules) {
if (!rule.style || !rule.style?.fontFamily) if (!rule.style || !rule.style?.fontFamily)
continue; continue;
const selectorText = rule.selectorText; const selectorText = rule.selectorText;
const fontFamily = rule.style.fontFamily; const fontFamily = rule.style.fontFamily;
// 'inherit' kann nicht mit anderen Fonts kombiniert werden
if (fontFamily == 'inherit') if (fontFamily == 'inherit')
continue; continue;
// Bereits modifizierte Selektoren ignorieren
if (fontFamily.toLowerCase().includes(replacementFontName.toLowerCase())) if (fontFamily.toLowerCase().includes(replacementFontName.toLowerCase()))
continue; continue;
@@ -91,39 +75,30 @@
} }
} }
catch (e) { catch (e) {
// Manche Stylesheets sind wegen CORS nicht zugreifbar
} }
} }
return fontFamilyRules; return fontFamilyRules;
}; };
/**
* Erstelle neues Style-Tag mit überschriebenen font-family Regeln
*/
const createNewStyleTag = (fontFamilyRules) => { const createNewStyleTag = (fontFamilyRules) => {
const style = document.createElement("style"); const style = document.createElement("style");
style.setAttribute("type", "text/css"); style.setAttribute("type", "text/css");
style.setAttribute("id", extentionStyleTagId); style.setAttribute("id", extentionStyleTagId);
fontFamilyRules.forEach((rule) => { fontFamilyRules.forEach((rule) => {
// Setze Country Flags Font als Hauptfont; Original als Fallback
style.textContent += `${rule.selectorText} { font-family: '${replacementFontName}', ${rule.fontFamily} !important; }\n`; style.textContent += `${rule.selectorText} { font-family: '${replacementFontName}', ${rule.fontFamily} !important; }\n`;
}); });
return style; return style;
}; };
/**
* Wende Custom Font Styles auf die Seite an
*/
const applyCustomFontStyles = () => { const applyCustomFontStyles = () => {
const existingSheet = document.getElementById(extentionStyleTagId); const existingSheet = document.getElementById(extentionStyleTagId);
const fontFamilyRules = extractFontFamilyRules(); const fontFamilyRules = extractFontFamilyRules();
const newStyleTag = createNewStyleTag(fontFamilyRules); const newStyleTag = createNewStyleTag(fontFamilyRules);
// Schreibe überschriebene Styles komplett neu
if (existingSheet) { if (existingSheet) {
existingSheet.parentNode.removeChild(existingSheet); existingSheet.parentNode.removeChild(existingSheet);
} }
@@ -134,19 +109,14 @@
document.head.appendChild(newStyleTag); document.head.appendChild(newStyleTag);
}; };
/**
* Bewahre Custom Fonts in inline styles
*/
const preserveCustomFonts = (element) => { const preserveCustomFonts = (element) => {
if (element == undefined) if (element == undefined)
return; return;
// Ignoriere Elemente ohne style-Attribut oder font-family
const inlineStyle = element.getAttribute('style'); const inlineStyle = element.getAttribute('style');
if (!inlineStyle || !inlineStyle.includes('font-family')) if (!inlineStyle || !inlineStyle.includes('font-family'))
return; return;
// Font family regex für Font (Gruppe 1) und !important Modifier (Gruppe 2)
const fontFamilyRegex = /font-family\s*:\s*([^;]+?)(\s*!important)?\s*(;|$)/; const fontFamilyRegex = /font-family\s*:\s*([^;]+?)(\s*!important)?\s*(;|$)/;
const match = fontFamilyRegex.exec(inlineStyle); const match = fontFamilyRegex.exec(inlineStyle);
@@ -161,59 +131,75 @@
element.style.setProperty('font-family', currentFontFamily, 'important'); element.style.setProperty('font-family', currentFontFamily, 'important');
}; };
/** const processInitialElements = () => {
* Initialisiere das Script document.querySelectorAll('[style*="font-family"]').forEach(preserveCustomFonts);
*/ };
const init = () => { const init = () => {
// Lade Font-Face
loadFontFace(); loadFontFace();
// Warte bis DOM bereit ist
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
applyCustomFontStyles(); applyCustomFontStyles();
processInitialElements();
}); });
} else { } else {
applyCustomFontStyles(); applyCustomFontStyles();
processInitialElements();
} }
// Beobachte Dokument auf dynamisch hinzugefügte Styles
let lastStyleSheets = new Set(Array.from(document.styleSheets).map(sheet => sheet.href || sheet.ownerNode?.textContent)); let lastStyleSheets = new Set(Array.from(document.styleSheets).map(sheet => sheet.href || sheet.ownerNode?.textContent));
const observer = new MutationObserver((mutations) => { const observer = new MutationObserver((mutations) => {
let stylesheetChanged = false; let stylesheetChanged = false;
const elementsToProcess = new Set();
mutations.forEach(mutation => { mutations.forEach(mutation => {
// Fokussiere nur auf <link> und <style> Elemente
mutation.addedNodes.forEach(node => { mutation.addedNodes.forEach(node => {
if (node.id === extentionStyleTagId || node.id === headStyleTagId) if (node.id === extentionStyleTagId || node.id === headStyleTagId)
return; return;
const isStylesheet = node.nodeName === 'LINK' && node.rel === 'stylesheet'; const isStylesheet = node.nodeName === 'LINK' && node.rel === 'stylesheet';
const isStyleNode = node.nodeName === 'STYLE'; const isStyleNode = node.nodeName === 'STYLE';
if (!isStylesheet && !isStyleNode)
return;
const newStylesheetIdentifier = isStylesheet ? node.href : node.textContent; if (isStylesheet || isStyleNode) {
if (lastStyleSheets.has(newStylesheetIdentifier)) const newStylesheetIdentifier = isStylesheet ? node.href : node.textContent;
if (!lastStyleSheets.has(newStylesheetIdentifier)) {
stylesheetChanged = true;
lastStyleSheets.add(newStylesheetIdentifier);
}
return; return;
}
stylesheetChanged = true; if (node.nodeType === Node.ELEMENT_NODE) {
lastStyleSheets.add(newStylesheetIdentifier); if (node.hasAttribute?.('style') && node.getAttribute('style').includes('font-family')) {
elementsToProcess.add(node);
}
node.querySelectorAll?.('[style*="font-family"]').forEach(el => elementsToProcess.add(el));
}
}); });
if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
const target = mutation.target;
if (target.hasAttribute('style') && target.getAttribute('style').includes('font-family')) {
elementsToProcess.add(target);
}
}
}); });
if (stylesheetChanged) { if (stylesheetChanged) {
applyCustomFontStyles(); applyCustomFontStyles();
} }
// Bewahre font-families aus style-Attributen elementsToProcess.forEach(preserveCustomFonts);
document.querySelectorAll('*').forEach(preserveCustomFonts);
}); });
// Beobachte document DOM-Element und alle neu hinzugefügten Elemente observer.observe(document, {
observer.observe(document, { childList: true, subtree: true }); childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style']
});
}; };
// Starte Initialisierung
init(); init();
})(); })();