6.6.1 - Alpha2 - 新增 pinyin 模块, 用于汉语拼音转换

This commit is contained in:
SuperMonster003
2024-12-04 22:42:36 +08:00
parent 4904b30d34
commit 0a8c648f9a
5 changed files with 191 additions and 4 deletions

View File

@@ -1,7 +1,10 @@
{
"$data": {
"v6.6.1": {
"released_date": "2024/12/03",
"released_date": "2024/12/04",
"feature": [
"pinyin 模块, 用于汉语拼音转换 (参阅 项目文档 > [汉语拼音](https://docs.autojs6.com/#/pinyin))"
],
"fix": [
"部分环境因回退版本过低而无法正常编译项目的问题",
"调用不存在的方法时可能出现的 \"非原始类型值\" 异常"

View File

@@ -193,6 +193,10 @@ dependencies /* Unclassified */ {
// Toaster
implementation("com.github.getActivity:Toaster:12.6")
implementation("com.github.getActivity:EasyWindow:10.3")
// pinyin4j
implementation("com.belerweb:pinyin4j:2.5.0")
}
dependencies /* MIME */ {

View File

@@ -71,6 +71,7 @@ import org.autojs.autojs.runtime.api.augment.ocr.OcrMLKit
import org.autojs.autojs.runtime.api.augment.ocr.OcrPaddle
import org.autojs.autojs.runtime.api.augment.ocr.OcrRapid
import org.autojs.autojs.runtime.api.augment.opencc.OpenCC
import org.autojs.autojs.runtime.api.augment.pinyin.Pinyin
import org.autojs.autojs.runtime.api.augment.plugins.Plugins
import org.autojs.autojs.runtime.api.augment.recorder.Recorder
import org.autojs.autojs.runtime.api.augment.s13n.S13n
@@ -761,6 +762,7 @@ class ScriptRuntime private constructor(builder: Builder) {
SysProps(this).augment(target, true)
SQLite(this).augment(target, true)
NanoID.augment(target, true)
Pinyin.augment(target, true)
augmentedApp.defineProp(Autojs::class.java.simpleName.lowercase(), augmentedAutojs)
}

View File

@@ -0,0 +1,178 @@
package org.autojs.autojs.runtime.api.augment.pinyin
import net.sourceforge.pinyin4j.PinyinHelper
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType.LOWERCASE
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType.UPPERCASE
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITHOUT_TONE
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITH_TONE_MARK
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType.WITH_TONE_NUMBER
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType.WITH_U_AND_COLON
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType.WITH_U_UNICODE
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType.WITH_V
import org.autojs.autojs.annotation.RhinoSingletonFunctionInterface
import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire
import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.Invokable
import org.autojs.autojs.util.RhinoUtils.coerceString
import org.autojs.autojs.util.RhinoUtils.coerceStringUppercase
import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.mozilla.javascript.Context
import org.mozilla.javascript.NativeObject
object Pinyin : Augmentable(), Invokable {
private const val DEFAULT_SEPARATOR = ""
private const val DEFAULT_CASE_TYPE_STRING = "LOWERCASE"
private val DEFAULT_CASE_TYPE = LOWERCASE
private const val DEFAULT_TONE_TYPE_STRING = "WITHOUT_TONE"
private val DEFAULT_TONE_TYPE = WITHOUT_TONE
private const val DEFAULT_V_CHAR_TYPE_STRING = "WITH_V"
private val DEFAULT_V_CHAR_TYPE = WITH_V
private val pinyinToneMap = mapOf(
// 单韵母
"a1" to "ā", "a2" to "á", "a3" to "ǎ", "a4" to "à", "a0" to "a",
"o1" to "ō", "o2" to "ó", "o3" to "ǒ", "o4" to "ò", "o0" to "o",
"e1" to "ē", "e2" to "é", "e3" to "ě", "e4" to "è", "e0" to "e",
"i1" to "ī", "i2" to "í", "i3" to "ǐ", "i4" to "ì", "i0" to "i",
"u1" to "ū", "u2" to "ú", "u3" to "ǔ", "u4" to "ù", "u0" to "u",
"ü1" to "ǖ", "ü2" to "ǘ", "ü3" to "ǚ", "ü4" to "ǜ", "ü0" to "ü",
"v1" to "ǖ", "v2" to "ǘ", "v3" to "ǚ", "v4" to "ǜ", "v0" to "ü",
"u:1" to "ǖ", "u:2" to "ǘ", "u:3" to "ǚ", "u:4" to "ǜ", "u:0" to "ü",
// 复韵母 - 普通
"ai1" to "āi", "ai2" to "ái", "ai3" to "ǎi", "ai4" to "ài", "ai0" to "ai",
"ei1" to "ēi", "ei2" to "éi", "ei3" to "ěi", "ei4" to "èi", "ei0" to "ei",
"ui1" to "", "ui2" to "", "ui3" to "", "ui4" to "", "ui0" to "ui",
"ao1" to "āo", "ao2" to "áo", "ao3" to "ǎo", "ao4" to "ào", "ao0" to "ao",
"ou1" to "ōu", "ou2" to "óu", "ou3" to "ǒu", "ou4" to "òu", "ou0" to "ou",
"iu1" to "", "iu2" to "", "iu3" to "", "iu4" to "", "iu0" to "iu",
"ie1" to "", "ie2" to "", "ie3" to "", "ie4" to "", "ie0" to "ie",
"üe1" to "üē", "üe2" to "üé", "üe3" to "üě", "üe4" to "üè", "üe0" to "üe",
"u:e1" to "üē", "u:e2" to "üé", "u:e3" to "üě", "u:e4" to "üè", "u:e0" to "üe",
"ve1" to "üē", "ve2" to "üé", "ve3" to "üě", "ve4" to "üè", "ve0" to "üe",
// 复韵母 - 特殊
"er1" to "ēr", "er2" to "ér", "er3" to "ěr", "er4" to "èr", "er0" to "er",
// 复韵母 - 前鼻韵母
"an1" to "ān", "an2" to "án", "an3" to "ǎn", "an4" to "àn", "an0" to "an",
"en1" to "ēn", "en2" to "én", "en3" to "ěn", "en4" to "èn", "en0" to "en",
"in1" to "īn", "in2" to "ín", "in3" to "ǐn", "in4" to "ìn", "in0" to "in",
"un1" to "ūn", "un2" to "ún", "un3" to "ǔn", "un4" to "ùn", "un0" to "un",
"ün1" to "ǖn", "ün2" to "ǘn", "ün3" to "ǚn", "ün4" to "ǜn", "ün0" to "ün",
"u:n1" to "ǖn", "u:n2" to "ǘn", "u:n3" to "ǚn", "u:n4" to "ǜn", "u:n0" to "ün",
"vn1" to "ǖn", "vn2" to "ǘn", "vn3" to "ǚn", "vn4" to "ǜn", "vn0" to "ün",
// 复韵母 - 后鼻韵母
"ang1" to "āng", "ang2" to "áng", "ang3" to "ǎng", "ang4" to "àng", "ang0" to "ang",
"eng1" to "ēng", "eng2" to "éng", "eng3" to "ěng", "eng4" to "èng", "eng0" to "eng",
"ing1" to "īng", "ing2" to "íng", "ing3" to "ǐng", "ing4" to "ìng", "ing0" to "ing",
"ong1" to "ōng", "ong2" to "óng", "ong3" to "ǒng", "ong4" to "òng", "ong0" to "ong"
)
override val selfAssignmentFunctions = listOf(
::`as`.name,
::of.name,
)
@RhinoSingletonFunctionInterface
override fun invoke(args: Array<out Any?>): String = ensureArgumentsLengthInRange(args, 1..2) { argList ->
of(argList)
}
@RhinoSingletonFunctionInterface
fun of(args: Array<out Any?>): String = ensureArgumentsLengthInRange(args, 1..2) { argList ->
val (string, options) = argList
val str = coerceString(string, "").takeIf { it.isNotEmpty() } ?: return@ensureArgumentsLengthInRange ""
var separator = DEFAULT_SEPARATOR
val opt = when (options) {
is String -> newNativeObject().also { separator = options }
is NativeObject -> options
else -> newNativeObject()
}
separator = opt.inquire(listOf("separator", "sep"), ::coerceString, separator)
val caseType = when (val case = opt.inquire(listOf("case", "caseType"))) {
is HanyuPinyinCaseType -> case
else -> when (coerceStringUppercase(case, DEFAULT_CASE_TYPE_STRING)) {
"LOWERCASE", "LOW", "L", "0" -> LOWERCASE
"UPPERCASE", "UP", "U", "1" -> UPPERCASE
else -> throw IllegalArgumentException("Invalid case type: ${Context.toString(case)}")
}
}
val toneType = when (val tone = opt.inquire(listOf("tone", "toneType"))) {
is HanyuPinyinToneType -> tone
else -> when (coerceStringUppercase(tone, DEFAULT_TONE_TYPE_STRING)) {
"WITH_TONE_NUMBER", "WITH_NUMBER", "NUMBER", "NUM" -> WITH_TONE_NUMBER
"WITHOUT_TONE", "NO_TONE", "NO", "FALSE", "0" -> WITHOUT_TONE
"WITH_TONE_MARK", "WITH_MARK", "MARK", "TRUE", "1" -> WITH_TONE_MARK
else -> throw IllegalArgumentException("Invalid tone type: ${Context.toString(tone)}")
}
}
val vCharType = when (val vChar = opt.inquire(listOf("v", "vChar", "vCharType"))) {
is HanyuPinyinVCharType -> vChar
else -> when (coerceStringUppercase(vChar, if (toneType == WITH_TONE_MARK) "WITH_U_UNICODE" else DEFAULT_V_CHAR_TYPE_STRING)) {
"WITH_U_AND_COLON", "U_AND_COLON", "U_COLON", "U:" -> WITH_U_AND_COLON
"WITH_V", "V" -> WITH_V
"WITH_U_UNICODE", "U_UNICODE", "UNICODE", "Ü" -> WITH_U_UNICODE
else -> throw IllegalArgumentException("Invalid v char type: ${Context.toString(vChar)}")
}
}
ofRhino(str, separator, caseType, toneType, vCharType)
}
@JvmStatic
@JvmOverloads
fun ofRhino(
str: String,
separator: String = DEFAULT_SEPARATOR,
caseType: HanyuPinyinCaseType = DEFAULT_CASE_TYPE,
toneType: HanyuPinyinToneType = DEFAULT_TONE_TYPE,
vCharType: HanyuPinyinVCharType = DEFAULT_V_CHAR_TYPE,
): String {
val format = HanyuPinyinOutputFormat().also {
it.caseType = caseType
it.toneType = toneType
it.vCharType = vCharType
}
val pinyinResult = StringBuilder()
str.forEach { ch ->
val pinyin = when (ch) {
in '\u4E00'..'\u9FA5' -> {
PinyinHelper.toHanyuPinyinStringArray(ch, format)?.firstOrNull() ?: ""
}
else -> ch.toString()
}
pinyinResult.append(pinyin).append(separator)
}
return pinyinResult.toString().trim()
}
@RhinoSingletonFunctionInterface
fun `as`(args: Array<out Any?>): String = ensureArgumentsOnlyOne(args) { o ->
convertToTonePinyin(coerceString(o, ""))
}
private fun convertToTonePinyin(input: String): String {
val regex = Regex("(üe|u:e|ve|ue|ang|eng|ing|ong|ai|ei|ui|ao|ou|iu|ie|er|an|en|in|un|ün|u:n|vn|[aoeiuüv])([0-4])")
return regex.replace(input) { matchResult ->
val pinyinBase = matchResult.groupValues[1]
val toneNumber = matchResult.groupValues[2]
pinyinToneMap[pinyinBase + toneNumber] ?: matchResult.value
}
}
}

View File

@@ -1,5 +1,5 @@
#Wed Dec 04 17:11:59 CST 2024
BUILD_TIME=1733303519833
#Wed Dec 04 22:38:06 CST 2024
BUILD_TIME=1733323086217
COMPILE_SDK_VERSION=34
JAVA_VERSION=23
JAVA_VERSION_MIN_RADICAL=0
@@ -17,6 +17,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=34
TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=2891
VERSION_BUILD=2892
VERSION_NAME=6.6.1 Alpha2
VSCODE_EXT_REQUIRED_VERSION=1.0.8