// ==UserScript==
// @name 港交所披露易高亮
// @namespace http://tampermonkey.net/
// @version 20250629
// @description 高亮 1201(L) 卖出、1101(L) 买入,并对所有代号追加说明,支持数字与括号间有空格
// @author xueqiu.com https://xueqiu.com/u/sybd
// @match https://di.hkex.com.hk/*
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 港交所代号说明 codemap
const codeMap = {
"100": "你首次取得须具报权益,原因是:",
"1001": "你买入了股份",
"1002": "你获给予股份",
"1003": "你成为股本衍生工具的持有人,或沽出或发行股本衍生工具,并因而具有以下的权利或责任(选择一项):",
"10031": "你有权购入相关股份",
"10032": "你有责任购入相关股份",
"10033": "如相关股份价格高于某个水平,你有权向另一人收取款项",
"10034": "如相关股份价格低于某个水平,你有责任向另一人支付款项",
"10035": "你具有上文10031至10034所提述的包含于合约或文书内的任何权利或责任",
"1004": "你取得了股份的保证权益",
"1005": "你继承了股份",
"1006": "你成为了持有股份权益的信托的受益人",
"1007": "你采取了步骤以执行你作为合资格借出人以保证方式持有的股份的权利",
"1009": "你就互相交换涉及相同的相关股份的文书,订立协议",
"1010": "你根据先旧后新配售,以承配人身分获配售股份",
"1011": "你根据先旧后新配售向承配人配售股份因而减少你的股份权益后,获发行新股份",
"1012": "你成为某个一致行动集团成员,或该一致行动集团某个成员取得了更多股份",
"1013": "任何其他事件(你必须在补充资料方格简述有关事件)",
"110": "你的股份权益的百分率水平有所上升,原因是:",
"1101": "你买入了股份",
"1102": "你获给予股份",
"1103": "你成为股本衍生工具的持有人,或沽出或发行股本衍生工具,并因而具有以下的权利或责任(选择一项):",
"11031": "你有权购入相关股份",
"11032": "你有责任购入相关股份",
"11033": "如相关股份价格高于某个水平,你有权向另一人收取款项",
"11034": "如相关股份价格低于某个水平,你有责任向另一人支付款项",
"11035": "你具有上文11031至11034所提述的包含于合约或文书内的任何权利或责任",
"1104": "你取得了股份的保证权益",
"1105": "你继承了股份",
"1106": "你成为了持有股份权益的信托的受益人",
"1107": "你采取了步骤以执行你作为合资格借出人以保证方式持有的股份的权利",
"1109": "你就互相交换涉及相同的相关股份的文书,订立协议",
"1110": "你根据先旧后新配售,以承配人身分获配售股份",
"1111": "你根据先旧后新配售向承配人配售股份因而减少你的股份权益后,获发行新股份",
"1112": "你成为某个一致行动集团成员,或该一致行动集团某个成员取得了更多股份",
"1113": "任何其他事件(你必须在补充资料方格简述有关事件)",
"120": "你的股份权益的百分率水平有所下降,原因是:",
"1201": "你完成出售股份",
"1202": "你将股份馈赠他人",
"1203": "你交付了根据股本衍生工具须交付的股份或款项",
"1204": "令你具有以下权利或责任的股本衍生工具未有行使便已到期或被注销(选择一项):",
"12041": "你有权购入相关股份",
"12042": "你有责任购入相关股份",
"12043": "如相关股份价格高于某个水平,你有权向另一人收取款项",
"12044": "如相关股份价格低于某个水平,你有责任向另一人支付款项",
"12045": "你具有上文12041至12044所提述的包含于合约或文书内的任何权利或责任",
"1205": "你不再持有股份的保证权益",
"1206": "你没有接纳或已出售供股的权利",
"1208": "你就互相交换涉及相同的相关股份的文书,订立协议",
"1209": "你根据先旧后新配售向承配人配售股份",
"1210": "在先旧后新配售中发行了新股份",
"1211": "你不再是某个一致行动集团成员,或该一致行动集团某个成员处置了部分股份",
"1213": "任何其他事件(你必须在补充资料方格简述有关事件)",
"130": "你的股份权益的性质有所改变,原因是:",
"1301": "股份已交付给你,及你先前并无就购入有关股份作出具报",
"1302": "你已就出售你持有权益的股份订立协议,但无须在4个交易日内交付有关股份",
"1303": "你已行使股本衍生工具下的股份的权利",
"1304": "在股本衍生工具下的股份的权利已针对你而行使",
"1305": "你已向合资格借出人以外的人提供股份权益作为保证",
"1306": "你向合资格借出人以外的人提供作为保证的股份权益已获解除",
"1307": "你已采取步骤以执行股份的保证权益或持有作为保证的有关股份的权利,及你不是合资格借出人",
"1308": "有关方面已采取步骤以针对你执行股份的保证权益或持有作为保证的股份的权利",
"1309": "你是遗嘱的受益人,及遗嘱执行人已将股份转移给你",
"1310": "你是信托的受益人,及受托人已将股份转移给你",
"1311": "你已向同意借入股份的人交付股份",
"1312": "你借出的股份已交还给你",
"1313": "你已根据证券借贷协议借出股份",
"1314": "你已收回某证券借贷协议下的股份",
"1315": "你已就你继续持有的股份作出信托声明",
"1316": "任何其他事件(你必须在补充资料方格简述有关事件)",
"140": "你变为持有1%或以上的股份的淡仓,或你于有关股份的淡仓的百分率水平有所上升,原因是:",
"1401": "你成为股本衍生工具的持有人,或沽出或发行股本衍生工具,并因而具有以下的权利或责任(选择一项):",
"14011": "你有权要求另一人提取相关股份",
"14012": "你有责任交付相关股份",
"14013": "如相关股份价格低于某个水平,你有权向另一人收取款项",
"14014": "如相关股份价格高于某个水平,你有责任向另一人支付款项",
"14015": "你具有上文14011至14014所提述的包含于合约或文书内的任何权利或责任",
"1402": "你已根据证券借贷协议借入股份",
"1403": "任何其他事件(你必须在补充资料方格简述有关事件)",
"150": "你不再持有1%或以上的股份的淡仓,或你于有关股份的淡仓的百分率水平有所下降,原因是:",
"1501": "令你具有以下权利或责任的股本衍生工具未有行使便已到期或被注销(选择一项):",
"15011": "你有权要求另一人提取相关股份",
"15012": "你有责任交付相关股份",
"15013": "如相关股份价格低于某个水平,你有权向另一人收取款项",
"15014": "如相关股份价格高于某个水平,你有责任向另一人支付款项",
"15015": "你具有上文15011至15014所提述的包含于合约或文书内的任何权利或责任",
"1502": "你已交还某证券借贷协议下的股份",
"1503": "任何其他事件(你必须在补充资料方格简述有关事件)",
"160": "核准借出代理人",
"1601": "核准借出代理人根据《证券及期货(权益披露 — 证券借贷)规则》第5(4)条作出通知(选择一项):",
"16011": "你于自己可供借出的股份中持有的股份权益的百分率水平被视为有所上升",
"16012": "你于自己可供借出的股份中持有的股份权益的百分率水平被视为有所下降",
"1602": "控制核准借出代理人的人根据《证券及期货(权益披露 — 证券借贷)规则》第5(4)条作出通知(选择一项):",
"16021": "你于核准借出代理人的可供借出的股份中持有的股份权益的百分率水平被视为有所上升",
"16022": "你于核准借出代理人的可供借出的股份中持有的股份权益的百分率水平被视为有所下降",
"170": "杂项",
"1701": "有关法团上市,或该上市法团某类股份上市",
"1702": "为移除旧资料而将通知送交存档(如你选择此代号,你必须在补充资料方格注明旧资料及指明载有新资料的方格)",
"1703": "因披露界线改变而将通知送交存档",
"1704": "因你不再持有上市法团股份的须具报权益而将通知送交存档(你必须在补充资料方格简述有关事件)",
"1710": "自愿披露(你必须在补充资料方格简述有关事件)",
"1711": "其他(你必须在补充资料方格简述有关事件)",
"2101": "实益拥有人",
"2103": "与另一人共同持有权益",
"2104": "代理人",
"2105": "包销商",
"2106": "持有股份的保证权益的人",
"2201": "你所控制的法团的权益",
"2202": "你的配偶的权益",
"2203": "你未满18岁的子女的权益",
"2301": "受托人",
"2304": "遗嘱执行人或遗产管理人",
"2305": "信托受益人(酌情权益除外)",
"2306": "另一人的代名人(被动受托人除外)",
"2307": "可影响受托人如何行使其酌情权的酌情信托成立人",
"2401": "属第317(1)(a)条所述的买入股份协议一方的一致行动人士",
"2402": "属第317(1)(b)条所述的作出贷款或提供保证以买入股份的人",
"2501": "其他(你必须在补充资料方格简述有关身分)",
"2502": "核准借出代理人",
"3101": "现金",
"3102": "现金以外的资产",
"3103": "交还股份∕债权证的权利",
"3104": "服务",
"4101": "上市衍生工具 - 以实物交收",
"4102": "上市衍生工具 - 以现金交收",
"4103": "上市衍生工具 - 可转换文书",
"4104": "上市衍生工具 - 其他(你必须在补充资料方格简述衍生工具类别)",
"4105": "非上市衍生工具 - 以实物交收",
"4106": "非上市衍生工具 - 以现金交收",
"4107": "非上市衍生工具 - 可转换文书",
"4108": "非上市衍生工具 - 其他(你必须在补充资料方格简述衍生工具类别)",
"5101": "信托受托人",
"5102": "信托受益人(酌情权益除外)",
"5103": "可影响受托人如何行使其酌情权的酌情信托成立人"
};
// 颜色规则
function getColor(code) {
if (code === '1201') return 'red';
if (code === '1101') return 'green';
return '#89CFF0'; // 其他
}
// 遍历文本节点并替换
function traverse(node) {
if (node.nodeType === Node.TEXT_NODE) {
let text = node.nodeValue;
let parent = node.parentNode;
let replaced = false;
// 只根据数字判断,不要求 (L) 或 (S)
// 确保数字前后都是合适的分隔符,避免匹配数字串的一部分
// (?<=^|[^\d,])(\d+)(?=[^\d,]|$)
// 前面不能是数字或逗号,后面不能是数字或逗号
const regex = /(?<=^|[^\d,])(\d+)(?=[^\d,]|$)/g;
let match;
let lastIndex = 0;
let fragments = [];
while ((match = regex.exec(text)) !== null) {
const code = match[1];
// 只处理 codeMap 里有的 code
if (codeMap[code]) {
// 前面的普通文本
if (match.index > lastIndex) {
fragments.push(document.createTextNode(text.slice(lastIndex, match.index)));
}
// 代码
let codeSpan = document.createElement('span');
codeSpan.style.backgroundColor = getColor(code);
codeSpan.style.color = (code === '1201' ? 'white' : (code === '1101' ? 'white' : 'black'));
codeSpan.textContent = code;
fragments.push(codeSpan);
// 注释
let descSpan = document.createElement('span');
descSpan.textContent = ' ' + codeMap[code];
descSpan.style.color = getColor(code);
fragments.push(descSpan);
lastIndex = match.index + match[0].length;
replaced = true;
}
}
// 剩余文本
if (replaced) {
if (lastIndex < text.length) {
fragments.push(document.createTextNode(text.slice(lastIndex)));
}
// 插入新节点
fragments.forEach(frag => parent.insertBefore(frag, node));
parent.removeChild(node);
}
} else if (node.nodeType === Node.ELEMENT_NODE && node.tagName !== 'SCRIPT' && node.tagName !== 'STYLE') {
// 递归遍历子节点
for (let i = 0; i < node.childNodes.length; i++) {
traverse(node.childNodes[i]);
}
}
}
// 启动遍历
traverse(document.body);
})();