Size
6.6 KB
Version
1.0.3
Created
Apr 5, 2026
Updated
19 days ago
A new extension
1// ==UserScript==
2// @name Extension for ui.appen.com.cn
3// @description A new extension
4// @version 1.0.3
5// @match https://*.ui.appen.com.cn/*
6// @icon https://ui.appen.com.cn/public/assets/favicon.png
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 // 半角标点符号到全角标点符号的映射
12 const punctuationMap = {
13 ',': ',',
14 '.': '。',
15 '?': '?',
16 '!': '!',
17 ':': ':',
18 ';': ';',
19 '(': '(',
20 ')': ')',
21 '[': '【',
22 ']': '】',
23 '{': '{',
24 '}': '}',
25 '"': '"',
26 "'": ''',
27 '<': '〈',
28 '>': '〉',
29 '&': '&',
30 '%': '%',
31 '$': '$',
32 '#': '#',
33 '@': '@',
34 '~': '~',
35 '`': '`',
36 '^': '^',
37 '*': '*',
38 '_': '_',
39 '-': '-',
40 '+': '+',
41 '=': '=',
42 '|': '|',
43 '\\': '\',
44 '/': '/'
45 };
46
47 // 转换函数:将半角标点转换为全角
48 function convertToFullWidth(text) {
49 let result = '';
50 for (let i = 0; i < text.length; i++) {
51 const char = text[i];
52 if (punctuationMap[char]) {
53 result += punctuationMap[char];
54 } else {
55 result += char;
56 }
57 }
58 return result;
59 }
60
61 // 处理输入事件
62 function handleInput(event) {
63 const element = event.target;
64
65 // 只处理文本输入框和文本区域
66 if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.isContentEditable) {
67 const cursorPos = element.selectionStart || 0;
68 const originalValue = element.value || element.textContent || '';
69 const convertedValue = convertToFullWidth(originalValue);
70
71 // 只有当值发生改变时才更新
72 if (originalValue !== convertedValue) {
73 console.log('标点符号转换:', originalValue, '->', convertedValue);
74
75 if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
76 element.value = convertedValue;
77 // 尝试保持光标位置
78 try {
79 element.setSelectionRange(cursorPos, cursorPos);
80 } catch (e) {
81 // 忽略错误
82 }
83 } else if (element.isContentEditable) {
84 element.textContent = convertedValue;
85 }
86 }
87 }
88 }
89
90 // 使用 MutationObserver 监听 DOM 变化
91 function observeDOM() {
92 const observer = new MutationObserver((mutations) => {
93 // 为每个新增的节点添加事件监听
94 mutations.forEach((mutation) => {
95 mutation.addedNodes.forEach((node) => {
96 if (node.nodeType === Node.ELEMENT_NODE) {
97 // 为新增元素添加输入监听
98 if (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA') {
99 node.addEventListener('input', handleInput);
100 }
101 // 查找子元素中的输入框
102 const inputs = node.querySelectorAll ? node.querySelectorAll('input, textarea, [contenteditable="true"]') : [];
103 inputs.forEach((input) => {
104 input.addEventListener('input', handleInput);
105 });
106 }
107 });
108 });
109 });
110
111 observer.observe(document.body, {
112 childList: true,
113 subtree: true
114 });
115
116 console.log('标点符号自动转换扩展已启动');
117 }
118
119 // 为现有的输入框添加监听
120 function addListenersToExistingInputs() {
121 const inputs = document.querySelectorAll('input, textarea, [contenteditable="true"]');
122 inputs.forEach((input) => {
123 input.addEventListener('input', handleInput);
124 });
125
126 // 尝试监听 iframe 内的内容
127 setTimeout(() => {
128 const iframes = document.querySelectorAll('iframe');
129 iframes.forEach((iframe) => {
130 try {
131 if (iframe.contentDocument) {
132 const iframeInputs = iframe.contentDocument.querySelectorAll('input, textarea, [contenteditable="true"]');
133 iframeInputs.forEach((input) => {
134 input.addEventListener('input', handleInput);
135 });
136
137 // 也监听 iframe 内的 DOM 变化
138 const iframeObserver = new MutationObserver((mutations) => {
139 mutations.forEach((mutation) => {
140 mutation.addedNodes.forEach((node) => {
141 if (node.nodeType === Node.ELEMENT_NODE) {
142 if (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA') {
143 node.addEventListener('input', handleInput);
144 }
145 const newInputs = node.querySelectorAll ? node.querySelectorAll('input, textarea, [contenteditable="true"]') : [];
146 newInputs.forEach((input) => {
147 input.addEventListener('input', handleInput);
148 });
149 }
150 });
151 });
152 });
153
154 iframeObserver.observe(iframe.contentDocument.body, {
155 childList: true,
156 subtree: true
157 });
158 }
159 } catch (e) {
160 console.log('无法访问iframe内容(可能是跨域限制):', e.message);
161 }
162 });
163 }, 1000);
164 }
165
166 // 初始化
167 function init() {
168 console.log('初始化标点符号自动转换扩展...');
169 addListenersToExistingInputs();
170 observeDOM();
171 }
172
173 // 等待页面加载完成
174 if (document.readyState === 'loading') {
175 document.addEventListener('DOMContentLoaded', init);
176 } else {
177 init();
178 }
179
180 // 同时也监听页面完全加载事件
181 window.addEventListener('load', () => {
182 setTimeout(init, 500);
183 });
184})();