// ==UserScript==
// @name بىلنەپ ئۈندىدار سالون ياردەمچىسى
// @namespace https://bilnap.com/
// @version 1.0
// @description bilnap公众号助手,方便编辑维吾尔文
// @match *://mp.weixin.qq.com/*
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function() {
'use strict';
// ساقلاش ۋە ئېلىش فۇنكسىيەلىرى
const saveValue = (key, value) => GM_setValue(key, value);
const getValue = (key, defaultValue) => GM_getValue(key, defaultValue);
// خەت نۇسخىسى مەشغۇلاتلىرى
const getFonts = () => getValue('fonts', ['UKIJ Ekran', 'UKIJ CJK', 'Alkatip']);
const saveFont = (newFont) => {
let fonts = getFonts();
if (!fonts.includes(newFont)) {
fonts.push(newFont);
saveValue('fonts', fonts);
}
};
// خەت نۇسخىسىنى ئۆزگەرتىش
const changeFont = (element, fontFamily) => {
if (element) {
element.style.setProperty('font-family', `${fontFamily}, Arial, sans-serif`, 'important');
}
};
const changeFonts = (fontFamily) => {
const editorFrame = document.getElementById('ueditor_0');
if (editorFrame && editorFrame.contentDocument) {
changeFont(editorFrame.contentDocument.body, fontFamily);
editorFrame.contentDocument.querySelectorAll('p, span, div').forEach(el => {
changeFont(el, fontFamily);
});
}
document.querySelectorAll('body, #js_title_main .js_article_title, .appmsg_preview_container .appmsg, .weui-desktop-publish__cover-item .weui-desktop-publish__cover__title, .bilnap-box, .bilnap-box .tab-button, p, span, div, h1, h2, h3, h4, h5, h6, a, button, input, textarea').forEach(el => {
changeFont(el, fontFamily);
});
};
// فونتنىڭ بار-يوقلۇقىنى تەكشۈرۈش فۇنكسىيەسى
const isFontAvailable = (font) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const testText = 'abcdefghijklmnopqrstuvwxyz0123456789';
context.font = '12px monospace';
const baselineWidth = context.measureText(testText).width;
context.font = `12px ${font}, monospace`;
return baselineWidth !== context.measureText(testText).width;
};
// مەۋجۇت فونتلارنى تەكشۈرۈش
const checkAvailableFonts = () => {
const commonUyghurFonts = ['UKIJ Ekran', 'UKIJ Tuz', 'UKIJ Basma', 'Alp Ekran', 'Alp Tuz', 'UKIJTor', 'UKIJ Kufi'];
const availableFonts = commonUyghurFonts.filter(isFontAvailable);
saveValue('availableFonts', availableFonts);
return availableFonts;
};
// فونت تاللىغۇچنى يېڭىلاش
const updateFontSelectors = () => {
const selector = document.getElementById('fontSelector');
const availableFonts = checkAvailableFonts();
const customFonts = getFonts().filter(font => !availableFonts.includes(font));
const allFonts = [...availableFonts, ...customFonts];
selector.innerHTML = allFonts.map(font => `<option value="${font}">${font}</option>`).join('');
selector.value = getValue('currentFont', 'UKIJ Ekran');
};
// كۆرۈنمە يۈزنى قۇرۇش
const createUI = () => {
const div = document.createElement('div');
div.className = 'bilnap-box';
div.style.direction = 'rtl';
div.innerHTML = `
<style>
* {
font-family: ${getValue('currentFont', 'UKIJ Ekran')}, Arial, sans-serif !important;
}
.bilnap-box {
font-family: ${getValue('currentFont', 'UKIJ Ekran')}, Arial, sans-serif;
}
.bilnap-box #myWeChatUI {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
cursor: move;
}
.bilnap-box #myWeChatButton {
padding: 0;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: #07C160;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.bilnap-box #myWeChatButton:hover {
transform: translateY(-2px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2);
}
.bilnap-box #myWeChatButton img {
width: 88%;
border-radius: 50%;
object-fit: cover;
}
.bilnap-box #myWeChatFrame {
display: none;
position: fixed;
top: 95px;
right: 20px;
background-color: white;
border: none;
border-radius: 15px;
padding: 25px;
z-index: 10000;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
width: 320px;
}
.bilnap-box #myWeChatFrame h3 {
color: #07C160;
margin-top: 0;
text-align: center;
margin-bottom: 20px;
font-size: 1.2em;
}
.bilnap-box #myWeChatOverlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
z-index: 9998;
backdrop-filter: blur(1.3px);
}
.bilnap-box select, .bilnap-box input {
width: 100%;
padding: 10px;
margin: 5px 0 10px 0;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
}
.bilnap-box button {
margin-top: 15px;
padding: 10px 15px;
background-color: #07C160;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: bold;
}
.bilnap-box button:hover {
background-color: #06AE56;
}
.bilnap-box p {
margin-bottom: 5px;
font-weight: bold;
}
input#newFontInput {
width: 93%;
}
.bilnap-box .tab-buttons {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
}
.bilnap-box .tab-button {
padding: 8px 15px;
background-color: #f0f0f0;
border: none;
border-radius: 20px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: bold;
}
.bilnap-box .tab-button.active {
background-color: #07C160;
color: white;
}
.bilnap-box .tab-content {
display: none;
}
.bilnap-box .tab-content.active {
display: block;
}
.bilnap-box .instructions {
margin-top: 15px;
padding: 10px;
background-color: #f9f9f9;
border-radius: 5px;
font-size: 14px;
line-height: 1.5;
}
.bilnap-box .version {
text-align: center;
margin-top: 20px;
font-size: 12px;
color: #888;
}
</style>
<div id="myWeChatUI">
<button id="myWeChatButton">
<img src="https://yurayli.izday.top/iUpload/sysAvatar/6684c540d5b4e.jpg" alt="باش سۈرەت">
</button>
</div>
<div id="myWeChatFrame">
<h3>بىلنەپ ئۈندىدار سالون ياردەمچىسى</h3>
<div class="tab-buttons">
<button class="tab-button active" data-tab="font-settings">خەت نۇسخىسى</button>
<button class="tab-button" data-tab="other-settings">تەڭشەك</button>
</div>
<div class="tab-content active" id="font-settings">
<p>خەت نۇسخىسى:</p>
<select id="fontSelector"></select>
<p>يېڭى خەت نۇسخىسى قوشۇش:</p>
<input type="text" id="newFontInput" placeholder="يېڭى خەت نۇسخىسىنىڭ ئىسمىنى كىرگۈزۈڭ">
<button id="addNewFontButton">قوشۇش</button>
</div>
<div class="tab-content" id="other-settings">
<h4>ئىشلىتىش قوللانمىسى</h4>
<div class="instructions">
<p>1. خەت نۇسخىسىنى ئۆزگەرتىش ئۈچۈن، "خەت نۇسخىسى" تەبىدىكى تىزىملىكتىن خالىغان خەت نۇسخىسىنى تاللاڭ.</p>
<p>2. يېڭى خەت نۇسخىسى قوشۇش ئۈچۈن، خەت نۇسخىسىنىڭ ئىسمىنى كىرگۈزۈپ "قوشۇش" كۇنۇپكىسىنى بېسىڭ.</p>
<p>3. قىستۇرمىنى يۆتكەش ئۈچۈن، يۇمىلاق كۇنۇپكىنى تۇتۇپ سۆرەڭ.</p>
<p>4. قىستۇرمىنى يوشۇرۇش ئۈچۈن، قارا تەگلىككە چېكىڭ.</p>
</div>
<div class="version">نۇسخا نومۇرى: 1.0</div>
</div>
</div>
<div id="myWeChatOverlay"></div>
`;
document.body.appendChild(div);
};
// كۇنۇپكا ۋە رامكا فۇنكسىيەسىنى قوشۇش
const setupUIInteractions = () => {
const button = document.getElementById('myWeChatButton');
const frame = document.getElementById('myWeChatFrame');
const overlay = document.getElementById('myWeChatOverlay');
const weChatUI = document.getElementById('myWeChatUI');
let isFrameVisible = false;
let isDragging = false;
let startX, startY, startLeft, startTop;
const startDragging = (e) => {
if (e.target === button || e.target === button.querySelector('img')) {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
startLeft = weChatUI.offsetLeft;
startTop = weChatUI.offsetTop;
weChatUI.style.transition = 'none';
e.preventDefault();
}
};
const drag = (e) => {
if (!isDragging) return;
e.preventDefault();
let newLeft = startLeft + e.clientX - startX;
let newTop = startTop + e.clientY - startY;
newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - weChatUI.offsetWidth));
newTop = Math.max(0, Math.min(newTop, window.innerHeight - weChatUI.offsetHeight));
weChatUI.style.left = newLeft + 'px';
weChatUI.style.top = newTop + 'px';
weChatUI.style.right = 'auto';
};
const stopDragging = () => {
if (isDragging) {
isDragging = false;
weChatUI.style.transition = 'all 0.3s ease';
}
};
weChatUI.addEventListener('mousedown', startDragging);
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', stopDragging);
button.addEventListener('click', (e) => {
if (!isDragging) {
isFrameVisible = !isFrameVisible;
frame.style.display = isFrameVisible ? 'block' : 'none';
overlay.style.display = isFrameVisible ? 'block' : 'none';
button.style.transform = isFrameVisible ? 'scale(1.2)' : 'scale(1)';
}
e.stopPropagation();
});
overlay.addEventListener('click', () => {
frame.style.display = 'none';
overlay.style.display = 'none';
button.style.transform = 'scale(1)';
isFrameVisible = false;
});
// تەب ئالماشتۇرۇش
document.querySelectorAll('.tab-button').forEach(button => {
button.addEventListener('click', () => {
const tabId = button.getAttribute('data-tab');
document.querySelectorAll('.tab-button').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
button.classList.add('active');
document.getElementById(tabId).classList.add('active');
});
});
// خەت نۇسخىسى تاللاش
document.getElementById('fontSelector').addEventListener('change', function() {
const selectedFont = this.value;
saveValue('currentFont', selectedFont);
changeFonts(selectedFont);
updateCSS(selectedFont);
});
// يېڭى خەت نۇسخىسى قوشۇش
document.getElementById('addNewFontButton').addEventListener('click', function() {
const newFont = document.getElementById('newFontInput').value.trim();
if (newFont) {
saveFont(newFont);
document.getElementById('newFontInput').value = '';
updateFontSelectors();
}
});
};
// iframe نى كۈتۈش ۋە كود قوشۇش
const waitForIframeAndInject = () => {
const checkInterval = setInterval(() => {
const editorFrame = document.getElementById('ueditor_0');
if (editorFrame && editorFrame.contentDocument && editorFrame.contentDocument.body) {
clearInterval(checkInterval);
const savedFont = getValue('currentFont', 'UKIJ Ekran');
if (savedFont) {
changeFonts(savedFont);
}
}
}, 100);
};
// يۆنىلىشنى تەڭشەش
const setDirection = (direction) => {
const editorFrame = document.getElementById('ueditor_0');
if (editorFrame) {
editorFrame.contentWindow.postMessage({
action: 'setDirection',
direction: direction
}, '*');
}
};
// يۆنىلىش كۇنۇپكىلىرىنى قوشۇش
const addDirectionButtons = () => {
const toolbar = document.querySelector('.edui-toolbar-primary');
if (toolbar && !document.querySelector('.direction-buttons')) {
const buttonContainer = document.createElement('div');
buttonContainer.className = 'direction-buttons edui7474 edui-box edui-combox js_toolbar_more edui-for-more toolbar_more edui-default';
buttonContainer.style.display = 'inline-block';
buttonContainer.style.marginLeft = '10px';
const createButton = (text, direction) => {
const button = document.createElement('button');
button.textContent = text;
button.className = 'edui-button-body';
button.style.cssText = `
display: inline-block;
padding: 5px 10px;
margin: 0 2px;
border: 1px solid #ccc;
background-color: #f7f7f7;
color: #333;
cursor: pointer;
border-radius: 3px;
font-size: 12px;
transition: all 0.3s ease;
`;
button.addEventListener('click', () => {
setDirection(direction);
button.style.backgroundColor = '#e6e6e6';
button.style.boxShadow = 'inset 0 3px 5px rgba(0,0,0,.125)';
setTimeout(() => {
button.style.backgroundColor = '#f7f7f7';
button.style.boxShadow = 'none';
}, 200);
});
button.addEventListener('mouseover', () => {
button.style.backgroundColor = '#e6e6e6';
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = '#f7f7f7';
});
return button;
};
const ltrButton = createButton('LTR', 'ltr');
const rtlButton = createButton('RTL', 'rtl');
buttonContainer.appendChild(ltrButton);
buttonContainer.appendChild(rtlButton);
toolbar.appendChild(buttonContainer);
}
};
// iframe غا كود قوشۇش
const injectIframeScript = () => {
const editorFrame = document.getElementById('ueditor_0');
if (editorFrame && editorFrame.contentDocument) {
const script = editorFrame.contentDocument.createElement('script');
script.textContent = `
window.addEventListener('message', function(event) {
if (event.data && event.data.action === 'setDirection') {
const direction = event.data.direction;
const textAlign = direction === 'rtl' ? 'right' : 'left';
// بارلىق ئېلېمېنتلارغا يۆنىلىش ۋە تېكىست توغرىلاش خاسلىقىنى قوللىنىش
const applyDirectionToElement = (element) => {
element.style.direction = direction;
element.style.textAlign = textAlign;
Array.from(element.children).forEach(applyDirectionToElement);
};
applyDirectionToElement(document.body);
window.parent.postMessage({
action: 'directionSet',
direction: direction
}, '*');
}
});
`;
editorFrame.contentDocument.head.appendChild(script);
}
};
// قۇرال ئىستونىنى كۆزىتىش
const observeToolbar = () => {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
addDirectionButtons();
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
};
// يېڭى فۇنكسىيە: خەت نۇسخىسىنى دائىم تەكشۈرۈش ۋە يېڭىلاش
const checkAndUpdateFonts = () => {
const currentFont = getValue('currentFont', 'UKIJ Ekran');
changeFonts(currentFont);
};
// CSS نى يېڭىلاش
const updateCSS = (fontFamily) => {
let style = document.getElementById('bilnap-custom-style');
if (!style) {
style = document.createElement('style');
style.id = 'bilnap-custom-style';
document.head.appendChild(style);
}
style.textContent = `
* {
font-family: ${fontFamily}, Arial, sans-serif !important;
}
`;
};
// ئاساسىي فۇنكسىيە
const init = () => {
createUI();
setupUIInteractions();
updateFontSelectors();
const currentFont = getValue('currentFont', 'UKIJ Ekran');
changeFonts(currentFont);
updateCSS(currentFont);
waitForIframeAndInject();
observeToolbar();
injectIframeScript();
// ھەر 1000 مىللىسېكۇنتتا بىر قېتىم خەت نۇسخىسىنى تەكشۈرۈش ۋە يېڭىلاش
setInterval(() => {
const currentFont = getValue('currentFont', 'UKIJ Ekran');
changeFonts(currentFont);
updateCSS(currentFont);
}, 1000);
};
// بەت يۈكلەنگەندە باشلاش
window.addEventListener('load', init);
})();