opencc-rust

调用 opencc-rust-wasm 转换中文

目前為 2020-11-03 提交的版本,檢視 最新版本

// ==UserScript==
// @name	opencc-rust
// @namespace	Forbidden Siren
// @version	  0.9.1
// @description 调用 opencc-rust-wasm 转换中文
// @include	*
// @match	*://*
// @grant	GM_getResourceText
// @grant	GM_getResourceURL
// @grant	GM_registerMenuCommand
// @run-at	document-start
//
// @require  https://greasyfork.org/scripts/413698-opencc-rust-wasm/code/opencc-rust-wasm.js?version=859508
// @resource opencc_wasm https://cdn.jsdelivr.net/gh/polyproline/opencc-rust@main/opencc_gc.wasm
// @resource  HKVariants	https://cdn.jsdelivr.net/npm/opencc-data/data/HKVariants.txt
// @resource  HKVariantsRev	https://cdn.jsdelivr.net/npm/opencc-data/data/HKVariantsRev.txt
// @resource  HKVariantsRevPhrases	https://cdn.jsdelivr.net/npm/opencc-data/data/HKVariantsRevPhrases.txt
// @resource  JPShinjitaiCharacters	https://cdn.jsdelivr.net/npm/opencc-data/data/JPShinjitaiCharacters.txt
// @resource  JPShinjitaiPhrases	https://cdn.jsdelivr.net/npm/opencc-data/data/JPShinjitaiPhrases.txt
// @resource  JPVariants	https://cdn.jsdelivr.net/npm/opencc-data/data/JPVariants.txt
// @resource  JPVariantsRev	https://cdn.jsdelivr.net/npm/opencc-data/data/JPVariantsRev.txt
// @resource  STCharacters	https://cdn.jsdelivr.net/npm/opencc-data/data/STCharacters.txt
// @resource  STPhrases	https://cdn.jsdelivr.net/npm/opencc-data/data/STPhrases.txt
// @resource  TSCharacters	https://cdn.jsdelivr.net/npm/opencc-data/data/TSCharacters.txt
// @resource  TSPhrases	https://cdn.jsdelivr.net/npm/opencc-data/data/TSPhrases.txt
// @resource  TWPhrasesIT	https://cdn.jsdelivr.net/npm/opencc-data/data/TWPhrasesIT.txt
// @resource  TWPhrasesName	https://cdn.jsdelivr.net/npm/opencc-data/data/TWPhrasesName.txt
// @resource  TWPhrasesOther	https://cdn.jsdelivr.net/npm/opencc-data/data/TWPhrasesOther.txt
// @resource  TWPhrasesRev	https://cdn.jsdelivr.net/npm/opencc-data/data/TWPhrasesRev.txt
// @resource  TWVariants	https://cdn.jsdelivr.net/npm/opencc-data/data/TWVariants.txt
// @resource  TWVariantsRev	https://cdn.jsdelivr.net/npm/opencc-data/data/TWVariantsRev.txt
// @resource  TWVariantsRevPhrases	https://cdn.jsdelivr.net/npm/opencc-data/data/TWVariantsRevPhrases.txt
// ==/UserScript==
(function () {
	"use strict";

	const ToSimple = [["HKVariantsRevPhrases", "HKVariantsRev"], ["TWPhrasesRev", "TWVariantsRevPhrases", "TWVariantsRev"], ["TSPhrases", "TSCharacters"]];// to Simple Chinese
	const ToTraditional = [["TWVariantsRevPhrases", "TWVariantsRev"], ["HKVariantsRevPhrases", "HKVariantsRev"], ["JPShinjitaiPhrases", "JPShinjitaiCharacters", "JPVariantsRev"], ["STPhrases", "STCharacters"]];
	const ToTaiwan = [["STPhrases", "STCharacters"], "TWVariants", "TWPhrases"];
	const ToHongKong = [["STPhrases", "STCharacters"], "HKVariants"];

	const NODE_DICT = ToSimple;
	const ExcludeTag = new RegExp("SCRIPT|HR|BR|TEXTAREA|META|MAP|AUDIO|VIDEO|BASE|NOSCRIPT|OBJECT");
	const ExcludeType = new RegExp("text|search|hidden");
    const Base64 = new RegExp("(?<=base64,).*");

	function convert_chinese_wasm() {
		function base64ToUint8Array(base64String) {
			const padding = "=".repeat((4 - base64String.length % 4) % 4);
			const base64 = (base64String + padding)
				.replace(/\-/g, "+")
				.replace(/_/g, "/");
			const rawData = window.atob(base64);
			let outputArray = new Uint8Array(rawData.length);
			for (let i = 0; i < rawData.length; ++i) {
				outputArray[i] = rawData.charCodeAt(i);
			}
			return outputArray;
		}
		const wasm = base64ToUint8Array(Base64.exec(GM_getResourceURL("opencc_wasm"))[0]);
		console.debug("OpenCC 正在加载");
		init(wasm).then(() => {
			let build = ConverterBuild.new();
			console.debug("OpenCC 加载字典");
			NODE_DICT.forEach(item => {
				if (Array.isArray(item)) {
					item.forEach(function (item) {
						build.adddict(GM_getResourceText(item));
					});
				} else {
					console.assert(typeof item == "string");
					build.adddict(GM_getResourceText(item));
				}
				build.group();
			});
			console.debug("OpenCC 加载字典完成");
			const converter = build.build();
			function translate(pNode) {
				var childs;
				if (pNode) {
					childs = pNode.childNodes;
				} else {
					childs = document.documentElement.childNodes;
				}
				if (childs) {
					for (let i = 0; i < childs.length; i++) {
						const child = childs.item(i);
						if (ExcludeTag.test(child.tagName)) continue;
						if (child.title) {
							converter.convert(child.title).then(text => {
								if (child.title != text) {
									child.title = text;
								}
							});
						}
						if (child.alt) {
							converter.convert(child.alt).then(text => {
								if (child.alt != text) {
									child.alt = text;
								}
							});
						}
						if (child.tagName == "INPUT" && !ExcludeType.test(child.type)) {
							if (child.value) {
								converter.convert(child.value).then(text => {
									if (child.value != text) {
										child.value = text;
									}
								});
							}
							if (child.placeholder) {
								converter.convert(child.placeholder).then(text => {
									if (child.placeholder != text) {
										child.placeholder = text;
									}
								});
							}
						} else if (child.nodeType == 3) {
							if (child.data) {
								converter.convert(child.data).then(text => {
									if (child.data != text) {
										child.data = text;
									}
								});
							}
						} else {
							if (child.nodeType == 1) {
								translate(child);
							}
						}
					}
				}
			}
			GM_registerMenuCommand("中文转换", translate);
			setTimeout(function () {
				translate();
				const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
				let observer = new MutationObserver(function (records) {
					records.map(function (record) {
						if (record.addedNodes) {
							[].forEach.call(record.addedNodes, function (item) {
								translate(item);
							});
						}
					});
				});
				const option = {
					"childList": true,
					"subtree": true,
					"characterData": true
				};
				observer.observe(document.body,option);
			}, 1000);
		});
	}
	convert_chinese_wasm();
})();