commit 96f689cf928f115324a8190068d211b919d19b62 Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue Aug 19 07:59:07 2025 +0000 Deploy to GitHub pages diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..efede6e --- /dev/null +++ b/404.html @@ -0,0 +1,34 @@ + + + + + + + + + Pangu Text + + + + + +

404

There's nothing here.
Take me home
+ + + diff --git a/KDoc/pangutext-android/images/anchor-copy-button.svg b/KDoc/pangutext-android/images/anchor-copy-button.svg new file mode 100644 index 0000000..19c1fa3 --- /dev/null +++ b/KDoc/pangutext-android/images/anchor-copy-button.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/KDoc/pangutext-android/images/arrow_down.svg b/KDoc/pangutext-android/images/arrow_down.svg new file mode 100644 index 0000000..639aaf1 --- /dev/null +++ b/KDoc/pangutext-android/images/arrow_down.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/KDoc/pangutext-android/images/burger.svg b/KDoc/pangutext-android/images/burger.svg new file mode 100644 index 0000000..fcca732 --- /dev/null +++ b/KDoc/pangutext-android/images/burger.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/KDoc/pangutext-android/images/copy-icon.svg b/KDoc/pangutext-android/images/copy-icon.svg new file mode 100644 index 0000000..2cb02ec --- /dev/null +++ b/KDoc/pangutext-android/images/copy-icon.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/KDoc/pangutext-android/images/copy-successful-icon.svg b/KDoc/pangutext-android/images/copy-successful-icon.svg new file mode 100644 index 0000000..c4b9538 --- /dev/null +++ b/KDoc/pangutext-android/images/copy-successful-icon.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/KDoc/pangutext-android/images/footer-go-to-link.svg b/KDoc/pangutext-android/images/footer-go-to-link.svg new file mode 100644 index 0000000..a87add7 --- /dev/null +++ b/KDoc/pangutext-android/images/footer-go-to-link.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/KDoc/pangutext-android/images/go-to-top-icon.svg b/KDoc/pangutext-android/images/go-to-top-icon.svg new file mode 100644 index 0000000..abc3d1c --- /dev/null +++ b/KDoc/pangutext-android/images/go-to-top-icon.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/KDoc/pangutext-android/images/homepage.svg b/KDoc/pangutext-android/images/homepage.svg new file mode 100644 index 0000000..e3c83b1 --- /dev/null +++ b/KDoc/pangutext-android/images/homepage.svg @@ -0,0 +1,3 @@ + + + diff --git a/KDoc/pangutext-android/images/logo-icon.svg b/KDoc/pangutext-android/images/logo-icon.svg new file mode 100644 index 0000000..e42f957 --- /dev/null +++ b/KDoc/pangutext-android/images/logo-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/abstract-class-kotlin.svg b/KDoc/pangutext-android/images/nav-icons/abstract-class-kotlin.svg new file mode 100644 index 0000000..19d6148 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/abstract-class-kotlin.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/abstract-class.svg b/KDoc/pangutext-android/images/nav-icons/abstract-class.svg new file mode 100644 index 0000000..6018203 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/abstract-class.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/annotation-kotlin.svg b/KDoc/pangutext-android/images/nav-icons/annotation-kotlin.svg new file mode 100644 index 0000000..b90f508 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/annotation-kotlin.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/annotation.svg b/KDoc/pangutext-android/images/nav-icons/annotation.svg new file mode 100644 index 0000000..b80c54b --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/annotation.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/class-kotlin.svg b/KDoc/pangutext-android/images/nav-icons/class-kotlin.svg new file mode 100644 index 0000000..797a242 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/class-kotlin.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/class.svg b/KDoc/pangutext-android/images/nav-icons/class.svg new file mode 100644 index 0000000..3f1ad16 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/class.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/enum-kotlin.svg b/KDoc/pangutext-android/images/nav-icons/enum-kotlin.svg new file mode 100644 index 0000000..775a7cc --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/enum-kotlin.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/enum.svg b/KDoc/pangutext-android/images/nav-icons/enum.svg new file mode 100644 index 0000000..fa7f247 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/enum.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/exception-class.svg b/KDoc/pangutext-android/images/nav-icons/exception-class.svg new file mode 100644 index 0000000..c0b2bde --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/exception-class.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/field-value.svg b/KDoc/pangutext-android/images/nav-icons/field-value.svg new file mode 100644 index 0000000..2771ee5 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/field-value.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/field-variable.svg b/KDoc/pangutext-android/images/nav-icons/field-variable.svg new file mode 100644 index 0000000..e2d2bbd --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/field-variable.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/function.svg b/KDoc/pangutext-android/images/nav-icons/function.svg new file mode 100644 index 0000000..f0da64a --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/function.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/interface-kotlin.svg b/KDoc/pangutext-android/images/nav-icons/interface-kotlin.svg new file mode 100644 index 0000000..5e16326 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/interface-kotlin.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/interface.svg b/KDoc/pangutext-android/images/nav-icons/interface.svg new file mode 100644 index 0000000..32063ba --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/interface.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/object.svg b/KDoc/pangutext-android/images/nav-icons/object.svg new file mode 100644 index 0000000..31f0ee3 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/object.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/nav-icons/typealias-kotlin.svg b/KDoc/pangutext-android/images/nav-icons/typealias-kotlin.svg new file mode 100644 index 0000000..f4bb238 --- /dev/null +++ b/KDoc/pangutext-android/images/nav-icons/typealias-kotlin.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/KDoc/pangutext-android/images/theme-toggle.svg b/KDoc/pangutext-android/images/theme-toggle.svg new file mode 100644 index 0000000..df86202 --- /dev/null +++ b/KDoc/pangutext-android/images/theme-toggle.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/KDoc/pangutext-android/index.html b/KDoc/pangutext-android/index.html new file mode 100644 index 0000000..57d1ded --- /dev/null +++ b/KDoc/pangutext-android/index.html @@ -0,0 +1,153 @@ + + + + + pangutext-android + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

pangutext-android

+
+

Packages

+
+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ + +
Link copied to clipboard
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ + +
Link copied to clipboard
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ + +
Link copied to clipboard
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/navigation.html b/KDoc/pangutext-android/navigation.html new file mode 100644 index 0000000..862a45e --- /dev/null +++ b/KDoc/pangutext-android/navigation.html @@ -0,0 +1,52 @@ +
+
pangutext-android
+
+ +
+ +
+ +
+
+ + + +
+
+ + + + + + +
+
+ + + +
+
+ diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/configure-pangu-text.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/configure-pangu-text.html new file mode 100644 index 0000000..a6abd1d --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/configure-pangu-text.html @@ -0,0 +1,80 @@ + + + + + configurePanguText + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

configurePanguText

+
+
abstract fun configurePanguText(config: PanguTextConfig)

Configure the PanguText.

Configuring this item separately will override global settings.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/index.html new file mode 100644 index 0000000..906fee0 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/index.html @@ -0,0 +1,104 @@ + + + + + PanguTextView + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

PanguTextView

+
interface PanguTextView

The PanguText config interface.

+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
abstract fun configurePanguText(config: PanguTextConfig)

Configure the PanguText.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/after-text-changed.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/after-text-changed.html new file mode 100644 index 0000000..535a28a --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/after-text-changed.html @@ -0,0 +1,80 @@ + + + + + afterTextChanged + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

afterTextChanged

+
+
open override fun afterTextChanged(editable: Editable?)
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/before-text-changed.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/before-text-changed.html new file mode 100644 index 0000000..d556410 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/before-text-changed.html @@ -0,0 +1,80 @@ + + + + + beforeTextChanged + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

beforeTextChanged

+
+
open override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int)
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/index.html new file mode 100644 index 0000000..e61a0cb --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/index.html @@ -0,0 +1,134 @@ + + + + + PanguTextWatcher + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

PanguTextWatcher

+

A TextWatcher that automatically applies PanguText to the text content.

You don't need to create it manually, use TextView.injectRealTimePanguText instead.

Parameters

base

the base TextView.

config

the configuration of PanguText.

+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
open override fun afterTextChanged(editable: Editable?)
+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
open override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int)
+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
open override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int)
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/on-text-changed.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/on-text-changed.html new file mode 100644 index 0000000..089d614 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/on-text-changed.html @@ -0,0 +1,80 @@ + + + + + onTextChanged + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

onTextChanged

+
+
open override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int)
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/index.html new file mode 100644 index 0000000..712a2cb --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.core/index.html @@ -0,0 +1,118 @@ + + + + + com.highcapable.pangutext.android.core + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

Package-level declarations

+
+
+
+
+
+

Types

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
interface PanguTextView

The PanguText config interface.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+

A TextWatcher that automatically applies PanguText to the text content.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/-pangu-text-config.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/-pangu-text-config.html new file mode 100644 index 0000000..f81f00b --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/-pangu-text-config.html @@ -0,0 +1,80 @@ + + + + + PanguTextConfig + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

PanguTextConfig

+
+
fun PanguTextConfig(copyFromGlobal: Boolean = true, body: PanguTextConfig.() -> Unit): <Error class: unknown class>

Create a new instance of PanguTextConfig.

Return

PanguTextConfig

Parameters

copyFromGlobal

whether to copy the PanguText.globalConfig, default is true.

body

the configuration body.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/index.html new file mode 100644 index 0000000..cc3badb --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/index.html @@ -0,0 +1,163 @@ + + + + + com.highcapable.pangutext.android.extension + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

Package-level declarations

+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun TextView.injectPanguText(injectHint: Boolean = true, config: PanguTextConfig = PanguText.globalConfig)

Inject PanguText to the current text content once.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun TextView.injectRealTimePanguText(injectHint: Boolean = true, config: PanguTextConfig = PanguText.globalConfig)

Inject PanguText to the current text content in real time.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun PanguTextConfig(copyFromGlobal: Boolean = true, body: PanguTextConfig.() -> Unit): <Error class: unknown class>

Create a new instance of PanguTextConfig.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun TextView.setHintWithPangu(text: CharSequence?, config: PanguTextConfig = PanguText.globalConfig)

Use PanguText.format to format the hint text content.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun TextView.setTextWithPangu(text: CharSequence?, config: PanguTextConfig = PanguText.globalConfig)

Use PanguText.format to format the text content.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/inject-pangu-text.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/inject-pangu-text.html new file mode 100644 index 0000000..b84e9b5 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/inject-pangu-text.html @@ -0,0 +1,80 @@ + + + + + injectPanguText + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

injectPanguText

+
+
fun TextView.injectPanguText(injectHint: Boolean = true, config: PanguTextConfig = PanguText.globalConfig)

Inject PanguText to the current text content once.

Receiver

TextView

Parameters

injectHint

whether to apply TextView.setHint, default is true.

config

the configuration of PanguText.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/inject-real-time-pangu-text.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/inject-real-time-pangu-text.html new file mode 100644 index 0000000..2ac1dbe --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/inject-real-time-pangu-text.html @@ -0,0 +1,80 @@ + + + + + injectRealTimePanguText + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

injectRealTimePanguText

+
+
fun TextView.injectRealTimePanguText(injectHint: Boolean = true, config: PanguTextConfig = PanguText.globalConfig)

Inject PanguText to the current text content in real time.

  • Note: Repeated inject will be ignored unless the current TextView is detached.

Receiver

TextView

Parameters

injectHint

whether to apply TextView.setHint, default is true.

config

the configuration of PanguText.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/set-hint-with-pangu.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/set-hint-with-pangu.html new file mode 100644 index 0000000..e53cb57 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/set-hint-with-pangu.html @@ -0,0 +1,80 @@ + + + + + setHintWithPangu + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

setHintWithPangu

+
+
fun TextView.setHintWithPangu(text: CharSequence?, config: PanguTextConfig = PanguText.globalConfig)

Use PanguText.format to format the hint text content.

Receiver

TextView

Parameters

text

the text content.

config

the configuration of PanguText.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/set-text-with-pangu.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/set-text-with-pangu.html new file mode 100644 index 0000000..ac285da --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.extension/set-text-with-pangu.html @@ -0,0 +1,80 @@ + + + + + setTextWithPangu + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

setTextWithPangu

+
+
fun TextView.setTextWithPangu(text: CharSequence?, config: PanguTextConfig = PanguText.globalConfig)

Use PanguText.format to format the text content.

Receiver

TextView

Parameters

text

the text content.

config

the configuration of PanguText.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/index.html new file mode 100644 index 0000000..220cfea --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/index.html @@ -0,0 +1,104 @@ + + + + + Companion + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

Companion

+
object Companion
+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun inject(context: Context): <Error class: unknown class>

Inject PanguTextFactory2 to the current LayoutInflater of context.

Inject PanguTextFactory2 to the current LayoutInflater.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/inject.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/inject.html new file mode 100644 index 0000000..2593084 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/inject.html @@ -0,0 +1,80 @@ + + + + + inject + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

inject

+
+
fun inject(context: Context): <Error class: unknown class>

Inject PanguTextFactory2 to the current LayoutInflater of context.

Simple Usage:

class MainActivity : AppCompactActivity() {

val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Inject here.
PanguTextFactory2.inject(this)
setContentView(binding.root)
}
}

Traditional Usage:

class MainActivity : Activity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Inject here.
PanguTextFactory2.inject(this)
setContentView(R.layout.activity_main)
}
}

Usage with BetterAndroid's AppBindingActivity:

class MainActivity : AppBindingActivity<ActivityMainBinding>() {

override fun onPrepareContentView(savedInstanceState: Bundle?): LayoutInflater {
val inflater = super.onPrepareContentView(savedInstanceState)
// Inject here.
PanguTextFactory2.inject(inflater)
return inflater
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Your code here.
}
}

Parameters

context

the current context.


Inject PanguTextFactory2 to the current LayoutInflater.

Parameters

inflater

the current inflater.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/index.html new file mode 100644 index 0000000..f631731 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/index.html @@ -0,0 +1,123 @@ + + + + + PanguTextFactory2 + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

PanguTextFactory2

+

Pangu text factory 2 for LayoutInflater.Factory2.

Parameters

base

the base factory.

+
+
+
+
+
+

Types

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
object Companion
+
+
+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
open override fun onCreateView(name: String, context: Context, attrs: AttributeSet): <Error class: unknown class>
open override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): <Error class: unknown class>
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/on-create-view.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/on-create-view.html new file mode 100644 index 0000000..4d4ee5a --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/on-create-view.html @@ -0,0 +1,80 @@ + + + + + onCreateView + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

onCreateView

+
+
open override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): <Error class: unknown class>
open override fun onCreateView(name: String, context: Context, attrs: AttributeSet): <Error class: unknown class>
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/index.html new file mode 100644 index 0000000..706be6e --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/index.html @@ -0,0 +1,104 @@ + + + + + PanguTextPatcher + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

PanguTextPatcher

+

Patcher for PanguText.

+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun patch(view: View, config: PanguTextConfig = PanguText.globalConfig)

Patch PanguText to the view.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/patch.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/patch.html new file mode 100644 index 0000000..4c15359 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/patch.html @@ -0,0 +1,80 @@ + + + + + patch + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

patch

+
+
fun patch(view: View, config: PanguTextConfig = PanguText.globalConfig)

Patch PanguText to the view.

Parameters

view

the view or view group.

config

the configuration of PanguText.

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/index.html new file mode 100644 index 0000000..ec2af24 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android.factory/index.html @@ -0,0 +1,118 @@ + + + + + com.highcapable.pangutext.android.factory + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

Package-level declarations

+
+
+
+
+
+

Types

+
+
+
+
+ + +
Link copied to clipboard
+
+
+ +
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+

Patcher for PanguText.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/cjk-spacing-ratio.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/cjk-spacing-ratio.html new file mode 100644 index 0000000..3913c47 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/cjk-spacing-ratio.html @@ -0,0 +1,80 @@ + + + + + cjkSpacingRatio + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

cjkSpacingRatio

+
+

The CJK spacing ratio, default is DEFAULT_CJK_SPACING_RATIO.

The larger the value, the smaller the spacing, and cannot be less than 0.1f.

It is recommended to adjust with caution, it will only affect the spacing of CJK characters.

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/copy.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/copy.html new file mode 100644 index 0000000..4ec3d00 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/copy.html @@ -0,0 +1,80 @@ + + + + + copy + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

copy

+
+
fun copy(body: PanguTextConfig.() -> Unit = {}): <Error class: unknown class>

Copy the current configuration.

Return

PanguTextConfig

Parameters

body

the configuration body.

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/exclude-patterns.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/exclude-patterns.html new file mode 100644 index 0000000..5fbadb2 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/exclude-patterns.html @@ -0,0 +1,80 @@ + + + + + excludePatterns + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

excludePatterns

+
+
val excludePatterns: <Error class: unknown class>

The regular expression for text content that needs to be excluded. PanguText processing will be skipped after matching these texts.

Usage:

val config: PanguTextConfig
// Exclude all URLs.
config.excludePatterns.add("https?://\\S+".toRegex())
// Exclude emoji symbol placeholder like "[doge]".
config.excludePatterns.add("\\[.*?]".toRegex())
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/index.html new file mode 100644 index 0000000..61c162b --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/index.html @@ -0,0 +1,183 @@ + + + + + PanguTextConfig + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

PanguTextConfig

+

The PanguText configuration.

+
+
+
+
+
+

Properties

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+

The CJK spacing ratio, default is DEFAULT_CJK_SPACING_RATIO.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+
val excludePatterns: <Error class: unknown class>

The regular expression for text content that needs to be excluded. PanguText processing will be skipped after matching these texts.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+

Whether to automatically re-measure the text width after processing.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+

Enable the PanguText.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+

Processed Spanned text (experimental).

+
+
+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun copy(body: PanguTextConfig.() -> Unit = {}): <Error class: unknown class>

Copy the current configuration.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-auto-remeasure-text.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-auto-remeasure-text.html new file mode 100644 index 0000000..775812f --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-auto-remeasure-text.html @@ -0,0 +1,80 @@ + + + + + isAutoRemeasureText + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

isAutoRemeasureText

+
+

Whether to automatically re-measure the text width after processing.

  • Note: PanguText after injecting text and changing the text, the width of TextView will not be calculated automatically. At this time, this feature will call TextView.setText to re-execute the measurements, which can fix every time in some dynamic layouts (such as RecyclerView) changes in text width, but may cause performance issues, you can choose to disable this feature. To prevent unnecessary performance overhead, this feature only takes effect on TextView with maxLines set to 1 or singleLine.

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-enabled.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-enabled.html new file mode 100644 index 0000000..3c8fb81 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-enabled.html @@ -0,0 +1,80 @@ + + + + + isEnabled + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

isEnabled

+
+

Enable the PanguText.

This is a global switch that can be used to enable or disable the PanguText processor.

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-processed-spanned.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-processed-spanned.html new file mode 100644 index 0000000..1050310 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-processed-spanned.html @@ -0,0 +1,80 @@ + + + + + isProcessedSpanned + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

isProcessedSpanned

+
+

Processed Spanned text (experimental).

  • Note: This feature is in experimental stage and may not be fully supported, if the text is not processed correctly, please disable this feature.

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/format.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/format.html new file mode 100644 index 0000000..662249c --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/format.html @@ -0,0 +1,80 @@ + + + + + format + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

format

+
+
fun format(resources: Resources, @Px textSize: Float, text: CharSequence, config: PanguTextConfig = globalConfig): CharSequence

Use PanguText to format specified text.

PanguText will automatically set PanguMarginSpan for some characters in the text to achieve white space typesetting effect without actually inserting any characters or changing the length of the original text.

This function will insert a style for the current given text without actually changing the string position in the text. If the current text is of type Spannable, it will return the original unmodified object, otherwise it will return the wrapped object SpannableString after.

Return

CharSequence

Parameters

resources

the current resources.

textSize

the text size (px).

text

text to be formatted.

config

the configuration of PanguText.

See also


fun format(text: CharSequence, whiteSpace: Char = ' ', config: PanguTextConfig = globalConfig): CharSequence

Use PanguText to format the current text content.

Using this function will add extra whiteSpace as character spacing to the text, changing the length of the original text.

Return

CharSequence

Parameters

text

text to be formatted.

whiteSpace

the spacing character, default is 'U+200A'.

config

the configuration of PanguText.

See also

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/global-config.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/global-config.html new file mode 100644 index 0000000..81489dc --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/global-config.html @@ -0,0 +1,80 @@ + + + + + globalConfig + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

globalConfig

+
+

The global configuration of PanguText.

+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/index.html new file mode 100644 index 0000000..d077efe --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/-pangu-text/index.html @@ -0,0 +1,123 @@ + + + + + PanguText + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

PanguText

+
object PanguText

The library core of Pangu text processor.

Bigger thanks for this project.

See also

PanguPatterns
+
+
+
+
+
+

Properties

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+

The global configuration of PanguText.

+
+
+
+
+
+
+
+

Functions

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
fun format(text: CharSequence, whiteSpace: Char = ' ', config: PanguTextConfig = globalConfig): CharSequence

Use PanguText to format the current text content.

fun format(resources: Resources, @Px textSize: Float, text: CharSequence, config: PanguTextConfig = globalConfig): CharSequence

Use PanguText to format specified text.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/index.html b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/index.html new file mode 100644 index 0000000..37288a7 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/com.highcapable.pangutext.android/index.html @@ -0,0 +1,118 @@ + + + + + com.highcapable.pangutext.android + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+

Package-level declarations

+
+
+
+
+
+

Types

+
+
+
+
+ + +
Link copied to clipboard
+
+
+
+
object PanguText

The library core of Pangu text processor.

+
+
+
+
+ +
+
+
+ + +
Link copied to clipboard
+
+
+
+

The PanguText configuration.

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/KDoc/pangutext-android/pangutext-android/package-list b/KDoc/pangutext-android/pangutext-android/package-list new file mode 100644 index 0000000..ebd5d29 --- /dev/null +++ b/KDoc/pangutext-android/pangutext-android/package-list @@ -0,0 +1,41 @@ +$dokka.format:html-v1 +$dokka.linkExtension:html +$dokka.location:com.highcapable.pangutext.android.core////PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.core/index.html +$dokka.location:com.highcapable.pangutext.android.core/PanguTextView///PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/index.html +$dokka.location:com.highcapable.pangutext.android.core/PanguTextView/configurePanguText/#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-view/configure-pangu-text.html +$dokka.location:com.highcapable.pangutext.android.core/PanguTextWatcher///PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/index.html +$dokka.location:com.highcapable.pangutext.android.core/PanguTextWatcher/afterTextChanged/#android.text.Editable?/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/after-text-changed.html +$dokka.location:com.highcapable.pangutext.android.core/PanguTextWatcher/beforeTextChanged/#kotlin.CharSequence?#kotlin.Int#kotlin.Int#kotlin.Int/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/before-text-changed.html +$dokka.location:com.highcapable.pangutext.android.core/PanguTextWatcher/onTextChanged/#kotlin.CharSequence?#kotlin.Int#kotlin.Int#kotlin.Int/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.core/-pangu-text-watcher/on-text-changed.html +$dokka.location:com.highcapable.pangutext.android.extension////PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.extension/index.html +$dokka.location:com.highcapable.pangutext.android.extension//PanguTextConfig/#kotlin.Boolean#kotlin.Function1[com.highcapable.pangutext.android.PanguTextConfig,kotlin.Unit]/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.extension/-pangu-text-config.html +$dokka.location:com.highcapable.pangutext.android.extension//injectPanguText/android.widget.TextView#kotlin.Boolean#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.extension/inject-pangu-text.html +$dokka.location:com.highcapable.pangutext.android.extension//injectRealTimePanguText/android.widget.TextView#kotlin.Boolean#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.extension/inject-real-time-pangu-text.html +$dokka.location:com.highcapable.pangutext.android.extension//setHintWithPangu/android.widget.TextView#kotlin.CharSequence?#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.extension/set-hint-with-pangu.html +$dokka.location:com.highcapable.pangutext.android.extension//setTextWithPangu/android.widget.TextView#kotlin.CharSequence?#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.extension/set-text-with-pangu.html +$dokka.location:com.highcapable.pangutext.android.factory////PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/index.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextFactory2.Companion///PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/index.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextFactory2.Companion/inject/#android.content.Context/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/inject.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextFactory2.Companion/inject/#android.view.LayoutInflater/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/-companion/inject.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextFactory2///PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/index.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextFactory2/onCreateView/#android.view.View?#kotlin.String#android.content.Context#android.util.AttributeSet/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/on-create-view.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextFactory2/onCreateView/#kotlin.String#android.content.Context#android.util.AttributeSet/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-factory2/on-create-view.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextPatcher///PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/index.html +$dokka.location:com.highcapable.pangutext.android.factory/PanguTextPatcher/patch/#android.view.View#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android.factory/-pangu-text-patcher/patch.html +$dokka.location:com.highcapable.pangutext.android////PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/index.html +$dokka.location:com.highcapable.pangutext.android/PanguText///PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text/index.html +$dokka.location:com.highcapable.pangutext.android/PanguText/format/#android.content.res.Resources#kotlin.Float#kotlin.CharSequence#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text/format.html +$dokka.location:com.highcapable.pangutext.android/PanguText/format/#kotlin.CharSequence#kotlin.Char#com.highcapable.pangutext.android.PanguTextConfig/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text/format.html +$dokka.location:com.highcapable.pangutext.android/PanguText/globalConfig/#/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text/global-config.html +$dokka.location:com.highcapable.pangutext.android/PanguTextConfig///PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/index.html +$dokka.location:com.highcapable.pangutext.android/PanguTextConfig/cjkSpacingRatio/#/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/cjk-spacing-ratio.html +$dokka.location:com.highcapable.pangutext.android/PanguTextConfig/copy/#kotlin.Function1[com.highcapable.pangutext.android.PanguTextConfig,kotlin.Unit]/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/copy.html +$dokka.location:com.highcapable.pangutext.android/PanguTextConfig/excludePatterns/#/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/exclude-patterns.html +$dokka.location:com.highcapable.pangutext.android/PanguTextConfig/isAutoRemeasureText/#/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-auto-remeasure-text.html +$dokka.location:com.highcapable.pangutext.android/PanguTextConfig/isEnabled/#/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-enabled.html +$dokka.location:com.highcapable.pangutext.android/PanguTextConfig/isProcessedSpanned/#/PointingToDeclaration/pangutext-android/com.highcapable.pangutext.android/-pangu-text-config/is-processed-spanned.html +com.highcapable.pangutext.android +com.highcapable.pangutext.android.core +com.highcapable.pangutext.android.extension +com.highcapable.pangutext.android.factory + diff --git a/KDoc/pangutext-android/scripts/clipboard.js b/KDoc/pangutext-android/scripts/clipboard.js new file mode 100644 index 0000000..7a4f33c --- /dev/null +++ b/KDoc/pangutext-android/scripts/clipboard.js @@ -0,0 +1,56 @@ +/* + * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +window.addEventListener('load', () => { + document.querySelectorAll('span.copy-icon').forEach(element => { + element.addEventListener('click', (el) => copyElementsContentToClipboard(element)); + }) + + document.querySelectorAll('span.anchor-icon').forEach(element => { + element.addEventListener('click', (el) => { + if(element.hasAttribute('pointing-to')){ + const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to') + copyTextToClipboard(element, location) + } + }); + }) +}) + +const copyElementsContentToClipboard = (element) => { + const selection = window.getSelection(); + const range = document.createRange(); + range.selectNodeContents(element.parentNode.parentNode); + selection.removeAllRanges(); + selection.addRange(range); + + copyAndShowPopup(element, () => selection.removeAllRanges()) +} + +const copyTextToClipboard = (element, text) => { + var textarea = document.createElement("textarea"); + textarea.textContent = text; + textarea.style.position = "fixed"; + document.body.appendChild(textarea); + textarea.select(); + + copyAndShowPopup(element, () => document.body.removeChild(textarea)) +} + +const copyAndShowPopup = (element, after) => { + try { + document.execCommand('copy'); + element.nextElementSibling.classList.add('active-popup'); + setTimeout(() => { + element.nextElementSibling.classList.remove('active-popup'); + }, 1200); + } catch (e) { + console.error('Failed to write to clipboard:', e) + } + finally { + if(after) after() + } +} + +const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0] + diff --git a/KDoc/pangutext-android/scripts/main.js b/KDoc/pangutext-android/scripts/main.js new file mode 100644 index 0000000..ba6c347 --- /dev/null +++ b/KDoc/pangutext-android/scripts/main.js @@ -0,0 +1,44 @@ +(()=>{var e={8527:e=>{e.exports=''},5570:e=>{e.exports=''},107:e=>{e.exports=''},7224:e=>{e.exports=''},538:e=>{e.exports=''},1924:(e,n,t)=>{"use strict";var r=t(210),o=t(5559),i=o(r("String.prototype.indexOf"));e.exports=function(e,n){var t=r(e,!!n);return"function"==typeof t&&i(e,".prototype.")>-1?o(t):t}},5559:(e,n,t)=>{"use strict";var r=t(8612),o=t(210),i=o("%Function.prototype.apply%"),a=o("%Function.prototype.call%"),l=o("%Reflect.apply%",!0)||r.call(a,i),c=o("%Object.getOwnPropertyDescriptor%",!0),u=o("%Object.defineProperty%",!0),s=o("%Math.max%");if(u)try{u({},"a",{value:1})}catch(e){u=null}e.exports=function(e){var n=l(r,a,arguments);if(c&&u){var t=c(n,"length");t.configurable&&u(n,"length",{value:1+s(0,e.length-(arguments.length-1))})}return n};var f=function(){return l(r,i,arguments)};u?u(e.exports,"apply",{value:f}):e.exports.apply=f},4184:(e,n)=>{var t; +/*! + Copyright (c) 2018 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/!function(){"use strict";var r={}.hasOwnProperty;function o(){for(var e=[],n=0;n{"use strict";e.exports=function(e,n){var t=this,r=t.constructor;return t.options=Object.assign({storeInstancesGlobally:!0},n||{}),t.callbacks={},t.directMap={},t.sequenceLevels={},t.resetTimer=null,t.ignoreNextKeyup=!1,t.ignoreNextKeypress=!1,t.nextExpectedAction=!1,t.element=e,t.addEvents(),t.options.storeInstancesGlobally&&r.instances.push(t),t},e.exports.prototype.bind=t(2207),e.exports.prototype.bindMultiple=t(3396),e.exports.prototype.unbind=t(9208),e.exports.prototype.trigger=t(9855),e.exports.prototype.reset=t(6214),e.exports.prototype.stopCallback=t(3450),e.exports.prototype.handleKey=t(3067),e.exports.prototype.addEvents=t(718),e.exports.prototype.bindSingle=t(8763),e.exports.prototype.getKeyInfo=t(5825),e.exports.prototype.pickBestAction=t(8608),e.exports.prototype.getReverseMap=t(3956),e.exports.prototype.getMatches=t(3373),e.exports.prototype.resetSequences=t(3346),e.exports.prototype.fireCallback=t(2684),e.exports.prototype.bindSequence=t(7103),e.exports.prototype.resetSequenceTimer=t(7309),e.exports.prototype.detach=t(7554),e.exports.instances=[],e.exports.reset=t(1822),e.exports.REVERSE_MAP=null},718:(e,n,t)=>{"use strict";e.exports=function(){var e=this,n=t(4323),r=e.element;e.eventHandler=t(9646).bind(e),n(r,"keypress",e.eventHandler),n(r,"keydown",e.eventHandler),n(r,"keyup",e.eventHandler)}},2207:e=>{"use strict";e.exports=function(e,n,t){return e=e instanceof Array?e:[e],this.bindMultiple(e,n,t),this}},3396:e=>{"use strict";e.exports=function(e,n,t){for(var r=0;r{"use strict";e.exports=function(e,n,r,o){var i=this;function a(n){return function(){i.nextExpectedAction=n,++i.sequenceLevels[e],i.resetSequenceTimer()}}function l(n){var a;i.fireCallback(r,n,e),"keyup"!==o&&(a=t(6770),i.ignoreNextKeyup=a(n)),setTimeout((function(){i.resetSequences()}),10)}i.sequenceLevels[e]=0;for(var c=0;c{"use strict";e.exports=function(e,n,t,r,o){var i=this;i.directMap[e+":"+t]=n;var a,l=(e=e.replace(/\s+/g," ")).split(" ");l.length>1?i.bindSequence(e,l,n,t):(a=i.getKeyInfo(e,t),i.callbacks[a.key]=i.callbacks[a.key]||[],i.getMatches(a.key,a.modifiers,{type:a.action},r,e,o),i.callbacks[a.key][r?"unshift":"push"]({callback:n,modifiers:a.modifiers,action:a.action,seq:r,level:o,combo:e}))}},7554:(e,n,t)=>{var r=t(4323).off;e.exports=function(){var e=this,n=e.element;r(n,"keypress",e.eventHandler),r(n,"keydown",e.eventHandler),r(n,"keyup",e.eventHandler)}},4323:e=>{function n(e,n,t,r){return!e.addEventListener&&(n="on"+n),(e.addEventListener||e.attachEvent).call(e,n,t,r),t}e.exports=n,e.exports.on=n,e.exports.off=function(e,n,t,r){return!e.removeEventListener&&(n="on"+n),(e.removeEventListener||e.detachEvent).call(e,n,t,r),t}},2684:(e,n,t)=>{"use strict";e.exports=function(e,n,r,o){this.stopCallback(n,n.target||n.srcElement,r,o)||!1===e(n,r)&&(t(1350)(n),t(6103)(n))}},5825:(e,n,t)=>{"use strict";e.exports=function(e,n){var r,o,i,a,l,c,u=[];for(r=t(4520)(e),a=t(7549),l=t(5355),c=t(8581),i=0;i{"use strict";e.exports=function(e,n,r,o,i,a){var l,c,u,s,f=this,p=[],d=r.type;"keypress"!==d||r.code&&"Arrow"===r.code.slice(0,5)||(f.callbacks["any-character"]||[]).forEach((function(e){p.push(e)}));if(!f.callbacks[e])return p;for(u=t(8581),"keyup"===d&&u(e)&&(n=[e]),l=0;l{"use strict";e.exports=function(){var e,n=this.constructor;if(!n.REVERSE_MAP)for(var r in n.REVERSE_MAP={},e=t(4766))r>95&&r<112||e.hasOwnProperty(r)&&(n.REVERSE_MAP[e[r]]=r);return n.REVERSE_MAP}},3067:(e,n,t)=>{"use strict";e.exports=function(e,n,r){var o,i,a,l,c=this,u={},s=0,f=!1;for(o=c.getMatches(e,n,r),i=0;i{"use strict";e.exports=function(e){var n,r=this;"number"!=typeof e.which&&(e.which=e.keyCode);var o=t(6770)(e);void 0!==o&&("keyup"!==e.type||r.ignoreNextKeyup!==o?(n=t(4610),r.handleKey(o,n(e),e)):r.ignoreNextKeyup=!1)}},5532:e=>{"use strict";e.exports=function(e,n){return e.sort().join(",")===n.sort().join(",")}},8608:e=>{"use strict";e.exports=function(e,n,t){return t||(t=this.getReverseMap()[e]?"keydown":"keypress"),"keypress"===t&&n.length&&(t="keydown"),t}},6214:e=>{"use strict";e.exports=function(){return this.callbacks={},this.directMap={},this}},7309:e=>{"use strict";e.exports=function(){var e=this;clearTimeout(e.resetTimer),e.resetTimer=setTimeout((function(){e.resetSequences()}),1e3)}},3346:e=>{"use strict";e.exports=function(e){var n=this;e=e||{};var t,r=!1;for(t in n.sequenceLevels)e[t]?r=!0:n.sequenceLevels[t]=0;r||(n.nextExpectedAction=!1)}},3450:e=>{"use strict";e.exports=function(e,n){if((" "+n.className+" ").indexOf(" combokeys ")>-1)return!1;var t=n.tagName.toLowerCase();return"input"===t||"select"===t||"textarea"===t||n.isContentEditable}},9855:e=>{"use strict";e.exports=function(e,n){return this.directMap[e+":"+n]&&this.directMap[e+":"+n]({},e),this}},9208:e=>{"use strict";e.exports=function(e,n){return this.bind(e,(function(){}),n)}},1822:e=>{"use strict";e.exports=function(){this.instances.forEach((function(e){e.reset()}))}},6770:(e,n,t)=>{"use strict";e.exports=function(e){var n,r;if(n=t(4766),r=t(5295),"keypress"===e.type){var o=String.fromCharCode(e.which);return e.shiftKey||(o=o.toLowerCase()),o}return void 0!==n[e.which]?n[e.which]:void 0!==r[e.which]?r[e.which]:String.fromCharCode(e.which).toLowerCase()}},4610:e=>{"use strict";e.exports=function(e){var n=[];return e.shiftKey&&n.push("shift"),e.altKey&&n.push("alt"),e.ctrlKey&&n.push("ctrl"),e.metaKey&&n.push("meta"),n}},8581:e=>{"use strict";e.exports=function(e){return"shift"===e||"ctrl"===e||"alt"===e||"meta"===e}},4520:e=>{"use strict";e.exports=function(e){return"+"===e?["+"]:e.split("+")}},1350:e=>{"use strict";e.exports=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1}},5355:e=>{"use strict";e.exports={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"}},7549:e=>{"use strict";e.exports={option:"alt",command:"meta",return:"enter",escape:"esc",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"}},5295:e=>{"use strict";e.exports={106:"*",107:"plus",109:"minus",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"}},4766:e=>{"use strict";e.exports={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",173:"minus",187:"plus",189:"minus",224:"meta"};for(var n=1;n<20;++n)e.exports[111+n]="f"+n;for(n=0;n<=9;++n)e.exports[n+96]=n},6103:e=>{"use strict";e.exports=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}},3362:()=>{var e;!function(){var e=Math.PI,n=2*e,t=e/180,r=document.createElement("div");document.head.appendChild(r);var o=self.ConicGradient=function(e){o.all.push(this),e=e||{},this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.repeating=!!e.repeating,this.size=e.size||Math.max(innerWidth,innerHeight),this.canvas.width=this.canvas.height=this.size;var n=e.stops;this.stops=(n||"").split(/\s*,(?![^(]*\))\s*/),this.from=0;for(var t=0;t0){var i=this.stops[0].clone();i.pos=0,this.stops.unshift(i)}if(void 0===this.stops[this.stops.length-1].pos)this.stops[this.stops.length-1].pos=1;else if(!this.repeating&&this.stops[this.stops.length-1].pos<1){var a=this.stops[this.stops.length-1].clone();a.pos=1,this.stops.push(a)}if(this.stops.forEach((function(e,n){if(void 0===e.pos){for(var t=n+1;this[t];t++)if(void 0!==this[t].pos){e.pos=this[n-1].pos+(this[t].pos-this[n-1].pos)/(t-n+1);break}}else n>0&&(e.pos=Math.max(e.pos,this[n-1].pos))}),this.stops),this.repeating){var l=(n=this.stops.slice())[n.length-1].pos-n[0].pos;for(t=0;this.stops[this.stops.length-1].pos<1&&t<1e4;t++)for(var c=0;c'},get png(){return this.canvas.toDataURL()},get r(){return Math.sqrt(2)*this.size/2},paint:function(){var e,n,r,o=this.context,i=this.r,a=this.size/2,l=0,c=this.stops[l];o.translate(this.size/2,this.size/2),o.rotate(-90*t),o.rotate(this.from*t),o.translate(-this.size/2,-this.size/2);for(var u=0;u<360;){if(u/360+1e-5>=c.pos){do{e=c,l++,c=this.stops[l]}while(c&&c!=e&&c.pos===e.pos);if(!c)break;var s=e.color+""==c.color+""&&e!=c;n=e.color.map((function(e,n){return c.color[n]-e}))}r=(u/360-e.pos)/(c.pos-e.pos);var f=s?c.color:n.map((function(n,t){var o=n*r+e.color[t];return t<3?255&o:o}));if(o.fillStyle="rgba("+f.join(",")+")",o.beginPath(),o.moveTo(a,a),s)var p=360*(c.pos-e.pos);else p=.5;var d=u*t,h=(d=Math.min(360*t,d))+p*t;h=Math.min(360*t,h+.02),o.arc(a,a,i,d,h),o.closePath(),o.fill(),u+=p}}},o.ColorStop=function(e,t){if(this.gradient=e,t){var r=t.match(/^(.+?)(?:\s+([\d.]+)(%|deg|turn|grad|rad)?)?(?:\s+([\d.]+)(%|deg|turn|grad|rad)?)?\s*$/);if(this.color=o.ColorStop.colorToRGBA(r[1]),r[2]){var i=r[3];"%"==i||"0"===r[2]&&!i?this.pos=r[2]/100:"turn"==i?this.pos=+r[2]:"deg"==i?this.pos=r[2]/360:"grad"==i?this.pos=r[2]/400:"rad"==i&&(this.pos=r[2]/n)}r[4]&&(this.next=new o.ColorStop(e,r[1]+" "+r[4]+r[5]))}},o.ColorStop.prototype={clone:function(){var e=new o.ColorStop(this.gradient);return e.color=this.color,e.pos=this.pos,e},toString:function(){return"rgba("+this.color.join(", ")+") "+100*this.pos+"%"}},o.ColorStop.colorToRGBA=function(e){if(!Array.isArray(e)&&-1==e.indexOf("from")){r.style.color=e;var n=getComputedStyle(r).color.match(/rgba?\(([\d.]+), ([\d.]+), ([\d.]+)(?:, ([\d.]+))?\)/);return n&&(n.shift(),(n=n.map((function(e){return+e})))[3]=isNaN(n[3])?1:n[3]),n||[0,0,0,0]}return e}}(),self.StyleFix&&((e=document.createElement("p")).style.backgroundImage="conic-gradient(white, black)",e.style.backgroundImage=PrefixFree.prefix+"conic-gradient(white, black)",e.style.backgroundImage||StyleFix.register((function(e,n){return e.indexOf("conic-gradient")>-1&&(e=e.replace(/(?:repeating-)?conic-gradient\(\s*((?:\([^()]+\)|[^;()}])+?)\)/g,(function(e,n){return new ConicGradient({stops:n,repeating:e.indexOf("repeating-")>-1})}))),e})))},9662:(e,n,t)=>{var r=t(7854),o=t(614),i=t(6330),a=r.TypeError;e.exports=function(e){if(o(e))return e;throw a(i(e)+" is not a function")}},9483:(e,n,t)=>{var r=t(7854),o=t(4411),i=t(6330),a=r.TypeError;e.exports=function(e){if(o(e))return e;throw a(i(e)+" is not a constructor")}},6077:(e,n,t)=>{var r=t(7854),o=t(614),i=r.String,a=r.TypeError;e.exports=function(e){if("object"==typeof e||o(e))return e;throw a("Can't set "+i(e)+" as a prototype")}},1223:(e,n,t)=>{var r=t(5112),o=t(30),i=t(3070),a=r("unscopables"),l=Array.prototype;null==l[a]&&i.f(l,a,{configurable:!0,value:o(null)}),e.exports=function(e){l[a][e]=!0}},1530:(e,n,t)=>{"use strict";var r=t(8710).charAt;e.exports=function(e,n,t){return n+(t?r(e,n).length:1)}},5787:(e,n,t)=>{var r=t(7854),o=t(7976),i=r.TypeError;e.exports=function(e,n){if(o(n,e))return e;throw i("Incorrect invocation")}},9670:(e,n,t)=>{var r=t(7854),o=t(111),i=r.String,a=r.TypeError;e.exports=function(e){if(o(e))return e;throw a(i(e)+" is not an object")}},7556:(e,n,t)=>{var r=t(7293);e.exports=r((function(){if("function"==typeof ArrayBuffer){var e=new ArrayBuffer(8);Object.isExtensible(e)&&Object.defineProperty(e,"a",{value:8})}}))},8533:(e,n,t)=>{"use strict";var r=t(2092).forEach,o=t(9341)("forEach");e.exports=o?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},8457:(e,n,t)=>{"use strict";var r=t(7854),o=t(9974),i=t(6916),a=t(7908),l=t(3411),c=t(7659),u=t(4411),s=t(6244),f=t(6135),p=t(8554),d=t(1246),h=r.Array;e.exports=function(e){var n=a(e),t=u(this),r=arguments.length,g=r>1?arguments[1]:void 0,v=void 0!==g;v&&(g=o(g,r>2?arguments[2]:void 0));var A,b,m,y,E,_,C=d(n),w=0;if(!C||this==h&&c(C))for(A=s(n),b=t?new this(A):h(A);A>w;w++)_=v?g(n[w],w):n[w],f(b,w,_);else for(E=(y=p(n,C)).next,b=t?new this:[];!(m=i(E,y)).done;w++)_=v?l(y,g,[m.value,w],!0):m.value,f(b,w,_);return b.length=w,b}},1318:(e,n,t)=>{var r=t(5656),o=t(1400),i=t(6244),a=function(e){return function(n,t,a){var l,c=r(n),u=i(c),s=o(a,u);if(e&&t!=t){for(;u>s;)if((l=c[s++])!=l)return!0}else for(;u>s;s++)if((e||s in c)&&c[s]===t)return e||s||0;return!e&&-1}};e.exports={includes:a(!0),indexOf:a(!1)}},2092:(e,n,t)=>{var r=t(9974),o=t(1702),i=t(8361),a=t(7908),l=t(6244),c=t(5417),u=o([].push),s=function(e){var n=1==e,t=2==e,o=3==e,s=4==e,f=6==e,p=7==e,d=5==e||f;return function(h,g,v,A){for(var b,m,y=a(h),E=i(y),_=r(g,v),C=l(E),w=0,x=A||c,k=n?x(h,C):t||p?x(h,0):void 0;C>w;w++)if((d||w in E)&&(m=_(b=E[w],w,y),e))if(n)k[w]=m;else if(m)switch(e){case 3:return!0;case 5:return b;case 6:return w;case 2:u(k,b)}else switch(e){case 4:return!1;case 7:u(k,b)}return f?-1:o||s?s:k}};e.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6),filterReject:s(7)}},1194:(e,n,t)=>{var r=t(7293),o=t(5112),i=t(7392),a=o("species");e.exports=function(e){return i>=51||!r((function(){var n=[];return(n.constructor={})[a]=function(){return{foo:1}},1!==n[e](Boolean).foo}))}},9341:(e,n,t)=>{"use strict";var r=t(7293);e.exports=function(e,n){var t=[][e];return!!t&&r((function(){t.call(null,n||function(){throw 1},1)}))}},3671:(e,n,t)=>{var r=t(7854),o=t(9662),i=t(7908),a=t(8361),l=t(6244),c=r.TypeError,u=function(e){return function(n,t,r,u){o(t);var s=i(n),f=a(s),p=l(s),d=e?p-1:0,h=e?-1:1;if(r<2)for(;;){if(d in f){u=f[d],d+=h;break}if(d+=h,e?d<0:p<=d)throw c("Reduce of empty array with no initial value")}for(;e?d>=0:p>d;d+=h)d in f&&(u=t(u,f[d],d,s));return u}};e.exports={left:u(!1),right:u(!0)}},206:(e,n,t)=>{var r=t(1702);e.exports=r([].slice)},4362:(e,n,t)=>{var r=t(206),o=Math.floor,i=function(e,n){var t=e.length,c=o(t/2);return t<8?a(e,n):l(e,i(r(e,0,c),n),i(r(e,c),n),n)},a=function(e,n){for(var t,r,o=e.length,i=1;i0;)e[r]=e[--r];r!==i++&&(e[r]=t)}return e},l=function(e,n,t,r){for(var o=n.length,i=t.length,a=0,l=0;a{var r=t(7854),o=t(3157),i=t(4411),a=t(111),l=t(5112)("species"),c=r.Array;e.exports=function(e){var n;return o(e)&&(n=e.constructor,(i(n)&&(n===c||o(n.prototype))||a(n)&&null===(n=n[l]))&&(n=void 0)),void 0===n?c:n}},5417:(e,n,t)=>{var r=t(7475);e.exports=function(e,n){return new(r(e))(0===n?0:n)}},3411:(e,n,t)=>{var r=t(9670),o=t(9212);e.exports=function(e,n,t,i){try{return i?n(r(t)[0],t[1]):n(t)}catch(n){o(e,"throw",n)}}},7072:(e,n,t)=>{var r=t(5112)("iterator"),o=!1;try{var i=0,a={next:function(){return{done:!!i++}},return:function(){o=!0}};a[r]=function(){return this},Array.from(a,(function(){throw 2}))}catch(e){}e.exports=function(e,n){if(!n&&!o)return!1;var t=!1;try{var i={};i[r]=function(){return{next:function(){return{done:t=!0}}}},e(i)}catch(e){}return t}},4326:(e,n,t)=>{var r=t(1702),o=r({}.toString),i=r("".slice);e.exports=function(e){return i(o(e),8,-1)}},648:(e,n,t)=>{var r=t(7854),o=t(1694),i=t(614),a=t(4326),l=t(5112)("toStringTag"),c=r.Object,u="Arguments"==a(function(){return arguments}());e.exports=o?a:function(e){var n,t,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(t=function(e,n){try{return e[n]}catch(e){}}(n=c(e),l))?t:u?a(n):"Object"==(r=a(n))&&i(n.callee)?"Arguments":r}},5631:(e,n,t)=>{"use strict";var r=t(3070).f,o=t(30),i=t(2248),a=t(9974),l=t(5787),c=t(408),u=t(654),s=t(6340),f=t(9781),p=t(2423).fastKey,d=t(9909),h=d.set,g=d.getterFor;e.exports={getConstructor:function(e,n,t,u){var s=e((function(e,r){l(e,d),h(e,{type:n,index:o(null),first:void 0,last:void 0,size:0}),f||(e.size=0),null!=r&&c(r,e[u],{that:e,AS_ENTRIES:t})})),d=s.prototype,v=g(n),A=function(e,n,t){var r,o,i=v(e),a=b(e,n);return a?a.value=t:(i.last=a={index:o=p(n,!0),key:n,value:t,previous:r=i.last,next:void 0,removed:!1},i.first||(i.first=a),r&&(r.next=a),f?i.size++:e.size++,"F"!==o&&(i.index[o]=a)),e},b=function(e,n){var t,r=v(e),o=p(n);if("F"!==o)return r.index[o];for(t=r.first;t;t=t.next)if(t.key==n)return t};return i(d,{clear:function(){for(var e=v(this),n=e.index,t=e.first;t;)t.removed=!0,t.previous&&(t.previous=t.previous.next=void 0),delete n[t.index],t=t.next;e.first=e.last=void 0,f?e.size=0:this.size=0},delete:function(e){var n=this,t=v(n),r=b(n,e);if(r){var o=r.next,i=r.previous;delete t.index[r.index],r.removed=!0,i&&(i.next=o),o&&(o.previous=i),t.first==r&&(t.first=o),t.last==r&&(t.last=i),f?t.size--:n.size--}return!!r},forEach:function(e){for(var n,t=v(this),r=a(e,arguments.length>1?arguments[1]:void 0);n=n?n.next:t.first;)for(r(n.value,n.key,this);n&&n.removed;)n=n.previous},has:function(e){return!!b(this,e)}}),i(d,t?{get:function(e){var n=b(this,e);return n&&n.value},set:function(e,n){return A(this,0===e?0:e,n)}}:{add:function(e){return A(this,e=0===e?0:e,e)}}),f&&r(d,"size",{get:function(){return v(this).size}}),s},setStrong:function(e,n,t){var r=n+" Iterator",o=g(n),i=g(r);u(e,n,(function(e,n){h(this,{type:r,target:e,state:o(e),kind:n,last:void 0})}),(function(){for(var e=i(this),n=e.kind,t=e.last;t&&t.removed;)t=t.previous;return e.target&&(e.last=t=t?t.next:e.state.first)?"keys"==n?{value:t.key,done:!1}:"values"==n?{value:t.value,done:!1}:{value:[t.key,t.value],done:!1}:(e.target=void 0,{value:void 0,done:!0})}),t?"entries":"values",!t,!0),s(n)}}},9320:(e,n,t)=>{"use strict";var r=t(1702),o=t(2248),i=t(2423).getWeakData,a=t(9670),l=t(111),c=t(5787),u=t(408),s=t(2092),f=t(2597),p=t(9909),d=p.set,h=p.getterFor,g=s.find,v=s.findIndex,A=r([].splice),b=0,m=function(e){return e.frozen||(e.frozen=new y)},y=function(){this.entries=[]},E=function(e,n){return g(e.entries,(function(e){return e[0]===n}))};y.prototype={get:function(e){var n=E(this,e);if(n)return n[1]},has:function(e){return!!E(this,e)},set:function(e,n){var t=E(this,e);t?t[1]=n:this.entries.push([e,n])},delete:function(e){var n=v(this.entries,(function(n){return n[0]===e}));return~n&&A(this.entries,n,1),!!~n}},e.exports={getConstructor:function(e,n,t,r){var s=e((function(e,o){c(e,p),d(e,{type:n,id:b++,frozen:void 0}),null!=o&&u(o,e[r],{that:e,AS_ENTRIES:t})})),p=s.prototype,g=h(n),v=function(e,n,t){var r=g(e),o=i(a(n),!0);return!0===o?m(r).set(n,t):o[r.id]=t,e};return o(p,{delete:function(e){var n=g(this);if(!l(e))return!1;var t=i(e);return!0===t?m(n).delete(e):t&&f(t,n.id)&&delete t[n.id]},has:function(e){var n=g(this);if(!l(e))return!1;var t=i(e);return!0===t?m(n).has(e):t&&f(t,n.id)}}),o(p,t?{get:function(e){var n=g(this);if(l(e)){var t=i(e);return!0===t?m(n).get(e):t?t[n.id]:void 0}},set:function(e,n){return v(this,e,n)}}:{add:function(e){return v(this,e,!0)}}),s}}},7710:(e,n,t)=>{"use strict";var r=t(2109),o=t(7854),i=t(1702),a=t(4705),l=t(1320),c=t(2423),u=t(408),s=t(5787),f=t(614),p=t(111),d=t(7293),h=t(7072),g=t(8003),v=t(9587);e.exports=function(e,n,t){var A=-1!==e.indexOf("Map"),b=-1!==e.indexOf("Weak"),m=A?"set":"add",y=o[e],E=y&&y.prototype,_=y,C={},w=function(e){var n=i(E[e]);l(E,e,"add"==e?function(e){return n(this,0===e?0:e),this}:"delete"==e?function(e){return!(b&&!p(e))&&n(this,0===e?0:e)}:"get"==e?function(e){return b&&!p(e)?void 0:n(this,0===e?0:e)}:"has"==e?function(e){return!(b&&!p(e))&&n(this,0===e?0:e)}:function(e,t){return n(this,0===e?0:e,t),this})};if(a(e,!f(y)||!(b||E.forEach&&!d((function(){(new y).entries().next()})))))_=t.getConstructor(n,e,A,m),c.enable();else if(a(e,!0)){var x=new _,k=x[m](b?{}:-0,1)!=x,S=d((function(){x.has(1)})),O=h((function(e){new y(e)})),B=!b&&d((function(){for(var e=new y,n=5;n--;)e[m](n,n);return!e.has(-0)}));O||((_=n((function(e,n){s(e,E);var t=v(new y,e,_);return null!=n&&u(n,t[m],{that:t,AS_ENTRIES:A}),t}))).prototype=E,E.constructor=_),(S||B)&&(w("delete"),w("has"),A&&w("get")),(B||k)&&w(m),b&&E.clear&&delete E.clear}return C[e]=_,r({global:!0,forced:_!=y},C),g(_,e),b||t.setStrong(_,e,A),_}},9920:(e,n,t)=>{var r=t(2597),o=t(3887),i=t(1236),a=t(3070);e.exports=function(e,n){for(var t=o(n),l=a.f,c=i.f,u=0;u{var r=t(5112)("match");e.exports=function(e){var n=/./;try{"/./"[e](n)}catch(t){try{return n[r]=!1,"/./"[e](n)}catch(e){}}return!1}},8544:(e,n,t)=>{var r=t(7293);e.exports=!r((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},4230:(e,n,t)=>{var r=t(1702),o=t(4488),i=t(1340),a=/"/g,l=r("".replace);e.exports=function(e,n,t,r){var c=i(o(e)),u="<"+n;return""!==t&&(u+=" "+t+'="'+l(i(r),a,""")+'"'),u+">"+c+""}},4994:(e,n,t)=>{"use strict";var r=t(3383).IteratorPrototype,o=t(30),i=t(9114),a=t(8003),l=t(7497),c=function(){return this};e.exports=function(e,n,t){var u=n+" Iterator";return e.prototype=o(r,{next:i(1,t)}),a(e,u,!1,!0),l[u]=c,e}},8880:(e,n,t)=>{var r=t(9781),o=t(3070),i=t(9114);e.exports=r?function(e,n,t){return o.f(e,n,i(1,t))}:function(e,n,t){return e[n]=t,e}},9114:e=>{e.exports=function(e,n){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:n}}},6135:(e,n,t)=>{"use strict";var r=t(4948),o=t(3070),i=t(9114);e.exports=function(e,n,t){var a=r(n);a in e?o.f(e,a,i(0,t)):e[a]=t}},8709:(e,n,t)=>{"use strict";var r=t(7854),o=t(9670),i=t(2140),a=r.TypeError;e.exports=function(e){if(o(this),"string"===e||"default"===e)e="string";else if("number"!==e)throw a("Incorrect hint");return i(this,e)}},654:(e,n,t)=>{"use strict";var r=t(2109),o=t(6916),i=t(1913),a=t(6530),l=t(614),c=t(4994),u=t(9518),s=t(7674),f=t(8003),p=t(8880),d=t(1320),h=t(5112),g=t(7497),v=t(3383),A=a.PROPER,b=a.CONFIGURABLE,m=v.IteratorPrototype,y=v.BUGGY_SAFARI_ITERATORS,E=h("iterator"),_="keys",C="values",w="entries",x=function(){return this};e.exports=function(e,n,t,a,h,v,k){c(t,n,a);var S,O,B,I=function(e){if(e===h&&R)return R;if(!y&&e in j)return j[e];switch(e){case _:case C:case w:return function(){return new t(this,e)}}return function(){return new t(this)}},T=n+" Iterator",P=!1,j=e.prototype,z=j[E]||j["@@iterator"]||h&&j[h],R=!y&&z||I(h),M="Array"==n&&j.entries||z;if(M&&(S=u(M.call(new e)))!==Object.prototype&&S.next&&(i||u(S)===m||(s?s(S,m):l(S[E])||d(S,E,x)),f(S,T,!0,!0),i&&(g[T]=x)),A&&h==C&&z&&z.name!==C&&(!i&&b?p(j,"name",C):(P=!0,R=function(){return o(z,this)})),h)if(O={values:I(C),keys:v?R:I(_),entries:I(w)},k)for(B in O)(y||P||!(B in j))&&d(j,B,O[B]);else r({target:n,proto:!0,forced:y||P},O);return i&&!k||j[E]===R||d(j,E,R,{name:h}),g[n]=R,O}},7235:(e,n,t)=>{var r=t(857),o=t(2597),i=t(6061),a=t(3070).f;e.exports=function(e){var n=r.Symbol||(r.Symbol={});o(n,e)||a(n,e,{value:i.f(e)})}},9781:(e,n,t)=>{var r=t(7293);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},317:(e,n,t)=>{var r=t(7854),o=t(111),i=r.document,a=o(i)&&o(i.createElement);e.exports=function(e){return a?i.createElement(e):{}}},8324:e=>{e.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},8509:(e,n,t)=>{var r=t(317)("span").classList,o=r&&r.constructor&&r.constructor.prototype;e.exports=o===Object.prototype?void 0:o},8886:(e,n,t)=>{var r=t(8113).match(/firefox\/(\d+)/i);e.exports=!!r&&+r[1]},256:(e,n,t)=>{var r=t(8113);e.exports=/MSIE|Trident/.test(r)},5268:(e,n,t)=>{var r=t(4326),o=t(7854);e.exports="process"==r(o.process)},8113:(e,n,t)=>{var r=t(5005);e.exports=r("navigator","userAgent")||""},7392:(e,n,t)=>{var r,o,i=t(7854),a=t(8113),l=i.process,c=i.Deno,u=l&&l.versions||c&&c.version,s=u&&u.v8;s&&(o=(r=s.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),e.exports=o},8008:(e,n,t)=>{var r=t(8113).match(/AppleWebKit\/(\d+)\./);e.exports=!!r&&+r[1]},748:e=>{e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2109:(e,n,t)=>{var r=t(7854),o=t(1236).f,i=t(8880),a=t(1320),l=t(3505),c=t(9920),u=t(4705);e.exports=function(e,n){var t,s,f,p,d,h=e.target,g=e.global,v=e.stat;if(t=g?r:v?r[h]||l(h,{}):(r[h]||{}).prototype)for(s in n){if(p=n[s],f=e.noTargetGet?(d=o(t,s))&&d.value:t[s],!u(g?s:h+(v?".":"#")+s,e.forced)&&void 0!==f){if(typeof p==typeof f)continue;c(p,f)}(e.sham||f&&f.sham)&&i(p,"sham",!0),a(t,s,p,e)}}},7293:e=>{e.exports=function(e){try{return!!e()}catch(e){return!0}}},7007:(e,n,t)=>{"use strict";t(4916);var r=t(1702),o=t(1320),i=t(2261),a=t(7293),l=t(5112),c=t(8880),u=l("species"),s=RegExp.prototype;e.exports=function(e,n,t,f){var p=l(e),d=!a((function(){var n={};return n[p]=function(){return 7},7!=""[e](n)})),h=d&&!a((function(){var n=!1,t=/a/;return"split"===e&&((t={}).constructor={},t.constructor[u]=function(){return t},t.flags="",t[p]=/./[p]),t.exec=function(){return n=!0,null},t[p](""),!n}));if(!d||!h||t){var g=r(/./[p]),v=n(p,""[e],(function(e,n,t,o,a){var l=r(e),c=n.exec;return c===i||c===s.exec?d&&!a?{done:!0,value:g(n,t,o)}:{done:!0,value:l(t,n,o)}:{done:!1}}));o(String.prototype,e,v[0]),o(s,p,v[1])}f&&c(s[p],"sham",!0)}},6677:(e,n,t)=>{var r=t(7293);e.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},2104:e=>{var n=Function.prototype,t=n.apply,r=n.bind,o=n.call;e.exports="object"==typeof Reflect&&Reflect.apply||(r?o.bind(t):function(){return o.apply(t,arguments)})},9974:(e,n,t)=>{var r=t(1702),o=t(9662),i=r(r.bind);e.exports=function(e,n){return o(e),void 0===n?e:i?i(e,n):function(){return e.apply(n,arguments)}}},7065:(e,n,t)=>{"use strict";var r=t(7854),o=t(1702),i=t(9662),a=t(111),l=t(2597),c=t(206),u=r.Function,s=o([].concat),f=o([].join),p={},d=function(e,n,t){if(!l(p,n)){for(var r=[],o=0;o{var n=Function.prototype.call;e.exports=n.bind?n.bind(n):function(){return n.apply(n,arguments)}},6530:(e,n,t)=>{var r=t(9781),o=t(2597),i=Function.prototype,a=r&&Object.getOwnPropertyDescriptor,l=o(i,"name"),c=l&&"something"===function(){}.name,u=l&&(!r||r&&a(i,"name").configurable);e.exports={EXISTS:l,PROPER:c,CONFIGURABLE:u}},1702:e=>{var n=Function.prototype,t=n.bind,r=n.call,o=t&&t.bind(r);e.exports=t?function(e){return e&&o(r,e)}:function(e){return e&&function(){return r.apply(e,arguments)}}},5005:(e,n,t)=>{var r=t(7854),o=t(614),i=function(e){return o(e)?e:void 0};e.exports=function(e,n){return arguments.length<2?i(r[e]):r[e]&&r[e][n]}},1246:(e,n,t)=>{var r=t(648),o=t(8173),i=t(7497),a=t(5112)("iterator");e.exports=function(e){if(null!=e)return o(e,a)||o(e,"@@iterator")||i[r(e)]}},8554:(e,n,t)=>{var r=t(7854),o=t(6916),i=t(9662),a=t(9670),l=t(6330),c=t(1246),u=r.TypeError;e.exports=function(e,n){var t=arguments.length<2?c(e):n;if(i(t))return a(o(t,e));throw u(l(e)+" is not iterable")}},8173:(e,n,t)=>{var r=t(9662);e.exports=function(e,n){var t=e[n];return null==t?void 0:r(t)}},647:(e,n,t)=>{var r=t(1702),o=t(7908),i=Math.floor,a=r("".charAt),l=r("".replace),c=r("".slice),u=/\$([$&'`]|\d{1,2}|<[^>]*>)/g,s=/\$([$&'`]|\d{1,2})/g;e.exports=function(e,n,t,r,f,p){var d=t+e.length,h=r.length,g=s;return void 0!==f&&(f=o(f),g=u),l(p,g,(function(o,l){var u;switch(a(l,0)){case"$":return"$";case"&":return e;case"`":return c(n,0,t);case"'":return c(n,d);case"<":u=f[c(l,1,-1)];break;default:var s=+l;if(0===s)return o;if(s>h){var p=i(s/10);return 0===p?o:p<=h?void 0===r[p-1]?a(l,1):r[p-1]+a(l,1):o}u=r[s-1]}return void 0===u?"":u}))}},7854:(e,n,t)=>{var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof t.g&&t.g)||function(){return this}()||Function("return this")()},2597:(e,n,t)=>{var r=t(1702),o=t(7908),i=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,n){return i(o(e),n)}},3501:e=>{e.exports={}},490:(e,n,t)=>{var r=t(5005);e.exports=r("document","documentElement")},4664:(e,n,t)=>{var r=t(9781),o=t(7293),i=t(317);e.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},8361:(e,n,t)=>{var r=t(7854),o=t(1702),i=t(7293),a=t(4326),l=r.Object,c=o("".split);e.exports=i((function(){return!l("z").propertyIsEnumerable(0)}))?function(e){return"String"==a(e)?c(e,""):l(e)}:l},9587:(e,n,t)=>{var r=t(614),o=t(111),i=t(7674);e.exports=function(e,n,t){var a,l;return i&&r(a=n.constructor)&&a!==t&&o(l=a.prototype)&&l!==t.prototype&&i(e,l),e}},2788:(e,n,t)=>{var r=t(1702),o=t(614),i=t(5465),a=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(e){return a(e)}),e.exports=i.inspectSource},2423:(e,n,t)=>{var r=t(2109),o=t(1702),i=t(3501),a=t(111),l=t(2597),c=t(3070).f,u=t(8006),s=t(1156),f=t(2050),p=t(9711),d=t(6677),h=!1,g=p("meta"),v=0,A=function(e){c(e,g,{value:{objectID:"O"+v++,weakData:{}}})},b=e.exports={enable:function(){b.enable=function(){},h=!0;var e=u.f,n=o([].splice),t={};t[g]=1,e(t).length&&(u.f=function(t){for(var r=e(t),o=0,i=r.length;o{var r,o,i,a=t(8536),l=t(7854),c=t(1702),u=t(111),s=t(8880),f=t(2597),p=t(5465),d=t(6200),h=t(3501),g="Object already initialized",v=l.TypeError,A=l.WeakMap;if(a||p.state){var b=p.state||(p.state=new A),m=c(b.get),y=c(b.has),E=c(b.set);r=function(e,n){if(y(b,e))throw new v(g);return n.facade=e,E(b,e,n),n},o=function(e){return m(b,e)||{}},i=function(e){return y(b,e)}}else{var _=d("state");h[_]=!0,r=function(e,n){if(f(e,_))throw new v(g);return n.facade=e,s(e,_,n),n},o=function(e){return f(e,_)?e[_]:{}},i=function(e){return f(e,_)}}e.exports={set:r,get:o,has:i,enforce:function(e){return i(e)?o(e):r(e,{})},getterFor:function(e){return function(n){var t;if(!u(n)||(t=o(n)).type!==e)throw v("Incompatible receiver, "+e+" required");return t}}}},7659:(e,n,t)=>{var r=t(5112),o=t(7497),i=r("iterator"),a=Array.prototype;e.exports=function(e){return void 0!==e&&(o.Array===e||a[i]===e)}},3157:(e,n,t)=>{var r=t(4326);e.exports=Array.isArray||function(e){return"Array"==r(e)}},614:e=>{e.exports=function(e){return"function"==typeof e}},4411:(e,n,t)=>{var r=t(1702),o=t(7293),i=t(614),a=t(648),l=t(5005),c=t(2788),u=function(){},s=[],f=l("Reflect","construct"),p=/^\s*(?:class|function)\b/,d=r(p.exec),h=!p.exec(u),g=function(e){if(!i(e))return!1;try{return f(u,s,e),!0}catch(e){return!1}};e.exports=!f||o((function(){var e;return g(g.call)||!g(Object)||!g((function(){e=!0}))||e}))?function(e){if(!i(e))return!1;switch(a(e)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}return h||!!d(p,c(e))}:g},4705:(e,n,t)=>{var r=t(7293),o=t(614),i=/#|\.prototype\./,a=function(e,n){var t=c[l(e)];return t==s||t!=u&&(o(n)?r(n):!!n)},l=a.normalize=function(e){return String(e).replace(i,".").toLowerCase()},c=a.data={},u=a.NATIVE="N",s=a.POLYFILL="P";e.exports=a},111:(e,n,t)=>{var r=t(614);e.exports=function(e){return"object"==typeof e?null!==e:r(e)}},1913:e=>{e.exports=!1},7850:(e,n,t)=>{var r=t(111),o=t(4326),i=t(5112)("match");e.exports=function(e){var n;return r(e)&&(void 0!==(n=e[i])?!!n:"RegExp"==o(e))}},2190:(e,n,t)=>{var r=t(7854),o=t(5005),i=t(614),a=t(7976),l=t(3307),c=r.Object;e.exports=l?function(e){return"symbol"==typeof e}:function(e){var n=o("Symbol");return i(n)&&a(n.prototype,c(e))}},408:(e,n,t)=>{var r=t(7854),o=t(9974),i=t(6916),a=t(9670),l=t(6330),c=t(7659),u=t(6244),s=t(7976),f=t(8554),p=t(1246),d=t(9212),h=r.TypeError,g=function(e,n){this.stopped=e,this.result=n},v=g.prototype;e.exports=function(e,n,t){var r,A,b,m,y,E,_,C=t&&t.that,w=!(!t||!t.AS_ENTRIES),x=!(!t||!t.IS_ITERATOR),k=!(!t||!t.INTERRUPTED),S=o(n,C),O=function(e){return r&&d(r,"normal",e),new g(!0,e)},B=function(e){return w?(a(e),k?S(e[0],e[1],O):S(e[0],e[1])):k?S(e,O):S(e)};if(x)r=e;else{if(!(A=p(e)))throw h(l(e)+" is not iterable");if(c(A)){for(b=0,m=u(e);m>b;b++)if((y=B(e[b]))&&s(v,y))return y;return new g(!1)}r=f(e,A)}for(E=r.next;!(_=i(E,r)).done;){try{y=B(_.value)}catch(e){d(r,"throw",e)}if("object"==typeof y&&y&&s(v,y))return y}return new g(!1)}},9212:(e,n,t)=>{var r=t(6916),o=t(9670),i=t(8173);e.exports=function(e,n,t){var a,l;o(e);try{if(!(a=i(e,"return"))){if("throw"===n)throw t;return t}a=r(a,e)}catch(e){l=!0,a=e}if("throw"===n)throw t;if(l)throw a;return o(a),t}},3383:(e,n,t)=>{"use strict";var r,o,i,a=t(7293),l=t(614),c=t(30),u=t(9518),s=t(1320),f=t(5112),p=t(1913),d=f("iterator"),h=!1;[].keys&&("next"in(i=[].keys())?(o=u(u(i)))!==Object.prototype&&(r=o):h=!0),null==r||a((function(){var e={};return r[d].call(e)!==e}))?r={}:p&&(r=c(r)),l(r[d])||s(r,d,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:h}},7497:e=>{e.exports={}},6244:(e,n,t)=>{var r=t(7466);e.exports=function(e){return r(e.length)}},133:(e,n,t)=>{var r=t(7392),o=t(7293);e.exports=!!Object.getOwnPropertySymbols&&!o((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},8536:(e,n,t)=>{var r=t(7854),o=t(614),i=t(2788),a=r.WeakMap;e.exports=o(a)&&/native code/.test(i(a))},3929:(e,n,t)=>{var r=t(7854),o=t(7850),i=r.TypeError;e.exports=function(e){if(o(e))throw i("The method doesn't accept regular expressions");return e}},1574:(e,n,t)=>{"use strict";var r=t(9781),o=t(1702),i=t(6916),a=t(7293),l=t(1956),c=t(5181),u=t(5296),s=t(7908),f=t(8361),p=Object.assign,d=Object.defineProperty,h=o([].concat);e.exports=!p||a((function(){if(r&&1!==p({b:1},p(d({},"a",{enumerable:!0,get:function(){d(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},n={},t=Symbol(),o="abcdefghijklmnopqrst";return e[t]=7,o.split("").forEach((function(e){n[e]=e})),7!=p({},e)[t]||l(p({},n)).join("")!=o}))?function(e,n){for(var t=s(e),o=arguments.length,a=1,p=c.f,d=u.f;o>a;)for(var g,v=f(arguments[a++]),A=p?h(l(v),p(v)):l(v),b=A.length,m=0;b>m;)g=A[m++],r&&!i(d,v,g)||(t[g]=v[g]);return t}:p},30:(e,n,t)=>{var r,o=t(9670),i=t(6048),a=t(748),l=t(3501),c=t(490),u=t(317),s=t(6200),f=s("IE_PROTO"),p=function(){},d=function(e){return" + About This Document | Pangu Text + + + + + +

About This Document

This document is powered by VuePressopen in new window.

License

Apache-2.0open in new window

Apache License Version 2.0
+
+Copyright (C) 2019 HighCapable
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+

Copyright © 2019 HighCapable

+ + + diff --git a/en/about/changelog.html b/en/about/changelog.html new file mode 100644 index 0000000..69b3ab6 --- /dev/null +++ b/en/about/changelog.html @@ -0,0 +1,34 @@ + + + + + + + + + Changelog | Pangu Text + + + + + +

Changelog

The version update history of PanguText is recorded here.

Pay Attention

We will only maintain the latest API version. If you are using an outdated API version, you voluntarily renounce any possibility of maintenance.

Notice

To avoid translation time consumption, the Changelog will use Google Translation from Chinese to English. Please refer to the original text for actual reference.

Time zone of version release date: UTC+8

pangutext-android

1.0.4 | 2025.08.16  latest

  • Exclude TextView's own TextWatcher set during injectPanguText execution to prevent repeated triggering of doOnTextChanged

1.0.3 | 2025.08.03  stale

1.0.2 | 2025.03.05  stale

  • Added exception handling in PanguTextFactory2 during injection to avoid interrupting the entire process during View initialization
  • Removed duplicate injection warning logs, now duplicate injections of PanguText will have no effect
  • Added PanguTextPatcher, which allows injecting PanguText using a new method

1.0.1 | 2025.02.11  stale

  • Fixed an issue where injecting PanguText could cause incorrect width measurement in TextView
  • Added isAutoRemeasureText to PanguTextConfig to control whether to automatically remeasure text width (applies to single-line text in TextView)

1.0.0 | 2025.02.10  stale

  • The first version is submitted to Maven

pangutext-compose

Not yet released.

+ + + diff --git a/en/about/contacts.html b/en/about/contacts.html new file mode 100644 index 0000000..3d0d47d --- /dev/null +++ b/en/about/contacts.html @@ -0,0 +1,34 @@ + + + + + + + + + Contact Us | Pangu Text + + + + + + + + + diff --git a/en/about/future.html b/en/about/future.html new file mode 100644 index 0000000..bb41215 --- /dev/null +++ b/en/about/future.html @@ -0,0 +1,34 @@ + + + + + + + + + Looking Toward the Future | Pangu Text + + + + + +

Looking Toward the Future

The future is bright and uncertain, let us look forward to the future development space of PanguText.

Future Plans

Features that PanguText may add later are included here.

Limitations of SpannableString

PanguText's main functionality on the Android platform currently comes from SpannableString, which has not yet fully resolved the issues of handling complex text styles and performance overhead.

Jetpack Compose Plan

PanguText will support Jetpack Compose in the future and plans to use AnnotatedString as the main text processing method to minimize intrusion into the underlying layer.

+ + + diff --git a/en/config/r8-proguard.html b/en/config/r8-proguard.html new file mode 100644 index 0000000..b92cd8b --- /dev/null +++ b/en/config/r8-proguard.html @@ -0,0 +1,34 @@ + + + + + + + + + R8 & Proguard Obfuscate | Pangu Text + + + + + +

R8 & Proguard Obfuscate

In most scenarios, the app packages can be compressed through obfuscation, here is an introduction to how to configure obfuscation rules.

PanguText does not require any additional obfuscation rules.

+ + + diff --git a/en/guide/home.html b/en/guide/home.html new file mode 100644 index 0000000..421d494 --- /dev/null +++ b/en/guide/home.html @@ -0,0 +1,34 @@ + + + + + + + + + Introduction | Pangu Text + + + + + +

Introduction

PanguText is a solution for CJK (Chinese, Japanese, Korean) and English word, half-width number spacing.

Background

This project was created because, until now, there hasn’t been a public solution to perfectly address the typography issues between Chinese, Japanese, Korean, and English. Typically, when mixing CJK (i.e. Chinese, Japanese, Korean) with English, aesthetic issues can arise—a historical legacy stemming from the differences in writing conventions between full-width and half-width characters. Although the W3C has now established CJK typography guidelines, only a few individuals or companies willing to adhere to these standards have adopted this approach.

Currently, the known vendor solutions are as follows:

  • Apple platforms (iOS, iPadOS, macOS, tvOS, watchOS) text typography solutions
  • Xiaomi’s (HyperOS) text typography optimization
  • OrginOS’s font-based text typography optimization

However, these solutions are closed-source and cannot be implemented on other platforms. We aim to provide an open-source solution adaptable to various scenarios, featuring low intrusiveness and easy integration, allowing more developers to effectively address text typography issues.

The primary inspiration for this project comes from pangu.jsopen in new window, which offers a set of regular expressions for CJK typography. We have optimized these solutions to format text across platforms without inserting extra space characters. We extend this approach further to explore additional possibilities.

Heartfelt thanks to the original developer of pangu.js for providing the foundational solution.

Effects

As you can see, the typography scheme of PanguText does not work by simply inserting spaces between CJK characters and English words. Instead, it leverages each platform's native handling to automatically add whitespace between these characters, ensuring minimal intrusion.

Before Applying (Top) vs. After Applying (Bottom)

Dynamic Application

PanguText supports dynamic application, which means it can add whitespace gaps to each character on-the-fly as you input text.

Developer's Perspective

I personally do not recommend manually inserting spaces between CJK and English characters for typographic refinement if your software or system natively supports enhanced typographic formatting.

The spacing can vary across fonts, which may lead to formatting issues and the insertion of undesired space characters.

In certain contexts, such as URLs, filenames, or hashtags containing “#”, these spaces are not acceptable.

However, in special scenarios—for example, within code comments or documentation—it can be beneficial to add spaces, as these areas typically do not employ automated formatting tools.

Another point to consider is the use of different punctuation marks in different languages. Avoid mixing full-width and half-width punctuation marks. If you must use half-width punctuation marks to annotate full-width text, ensure that the half-width marks are followed by a space to complete the character space (the same applies to English).

Language Requirement

It is recommended to use Kotlin as the preferred development language.

This project is entirely written in Kotlin and is compatible with Java in some parts, but it may not be fully compatible.

All demo & sample codes in the document will be described using Kotlin, if you don’t know how to use Kotlin at all, you may not get the best experience.

Contribution

The maintenance of this project is inseparable from the support and contributions of all developers.

This project is currently in its early stages, and there may still be some problems or lack of functions you need.

If possible, feel free to submit a PR to contribute features you think are needed to this project or go to GitHub Issuesopen in new window to make suggestions to us.

+ + + diff --git a/en/guide/quick-start.html b/en/guide/quick-start.html new file mode 100644 index 0000000..1190752 --- /dev/null +++ b/en/guide/quick-start.html @@ -0,0 +1,59 @@ + + + + + + + + + Quick Start | Pangu Text + + + + + +

Quick Start

Integrate PanguText into your project.

Project Requirements

The project needs to be created using Android Studio or IntelliJ IDEA and be of type Android or Kotlin Multiplatform project with integrated Kotlin environment dependencies.

  • Android Studio (It is recommended to get the latest version from hereopen in new window)

  • IntelliJ IDEA (It is recommended to get the latest version from hereopen in new window)

  • Kotlin 1.9.0+, Gradle 8+, Java 17+, Android Gradle Plugin 8+

Configure Repositories

The dependencies of PanguText are published in Maven Central and our public repository. You can use the following method to configure repositories.

We recommend using Kotlin DSL as the Gradle build script language and SweetDependencyopen in new window to manage dependencies.

Configure repositories in your project's SweetDependency configuration file.

repositories:
+  google:
+  maven-central:
+  # (Optional) You can add this URL to use our public repository
+  # When Sonatype-OSS fails and cannot publish dependencies, this repository is added as a backup
+  # For details, please visit: https://github.com/HighCapable/maven-repository
+  highcapable-maven-releases:
+    url: https://raw.githubusercontent.com/HighCapable/maven-repository/main/repository/releases
+

Traditional Method

Configure repositories in your project's build.gradle.kts.

repositories {
+    google()
+    mavenCentral()
+    // (Optional) You can add this URL to use our public repository
+    // When Sonatype-OSS fails and cannot publish dependencies, this repository is added as a backup
+    // For details, please visit: https://github.com/HighCapable/maven-repository
+    maven("https://raw.githubusercontent.com/HighCapable/maven-repository/main/repository/releases")
+}
+

Configure Java Version

Modify the Java version of Kotlin in your project's build.gradle.kts to 17 or above.

Kotlin DSL

android {
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_17
+        targetCompatibility = JavaVersion.VERSION_17
+    }
+    kotlinOptions {
+        jvmTarget = "17"
+    }
+}
+

Functional Overview

The project is divided into multiple modules: Android platform and Jetpack Compose (multiplatform). You can choose the module you wish to include as a dependency in your project.

Click the corresponding module below to view detailed feature descriptions.

Demo

You can find some examples below. Check out the corresponding demo projects to get a better understanding of how these features work and quickly select the functionality you need.

+ + + diff --git a/en/index.html b/en/index.html new file mode 100644 index 0000000..61dd3e9 --- /dev/null +++ b/en/index.html @@ -0,0 +1,34 @@ + + + + + + + + + Home | Pangu Text + + + + + + + + + diff --git a/en/library/android.html b/en/library/android.html new file mode 100644 index 0000000..d5fc392 --- /dev/null +++ b/en/library/android.html @@ -0,0 +1,204 @@ + + + + + + + + + Android | Pangu Text + + + + + +

Android

Maven CentralMaven metadata URLAndroid Min SDK

This is the core dependency for the Android platform. When using PanguText on Android, you need to include this module.

Configure Dependency

You can add this module to your project using the following method.

Add dependency in your project's SweetDependency configuration file.

libraries:
+  com.highcapable.pangutext:
+    pangutext-android:
+      version: +
+

Configure dependency in your project's build.gradle.kts.

implementation(com.highcapable.pangutext.pangutext.android)
+

Version Catalog

Add dependency in your project's gradle/libs.versions.toml.

[versions]
+pangutext-android = "<version>"
+
+[libraries]
+pangutext-android = { module = "com.highcapable.pangutext:pangutext-android", version.ref = "pangutext-android" }
+

Configure dependency in your project's build.gradle.kts.

implementation(libs.pangutext.android)
+

Please change <version> to the version displayed at the top of this document.

Traditional Method

Configure dependency in your project's build.gradle.kts.

implementation("com.highcapable.pangutext:pangutext-android:<version>")
+

Please change <version> to the version displayed at the top of this document.

Function Introduction

You can view the KDoc click hereopen in new window.

Implementation Principle

PanguText provides two methods for text formatting on the Android platform: SpannableString (does not alter the original text length) and direct insertion of whitespace characters (alters the original text length).

The first method, SpannableString, adds a Span with spacing to the character before the one that needs spacing, changing the text style without altering the string content. The rendering is done by the TextView layer (or manually using TextPaint based on Spanned for layout styling), achieving non-intrusive text styling.

This method also supports processing already styled text (Spanned), such as text created via Html.fromHtml.

However, it is currently experimental and may still have unexpected style errors. You can refer to the Personalized Configuration section below to disable it.

The dynamic application (injection) feature mainly targets the input state of EditText. It sets a custom TextWatcher for EditText to monitor input changes and formats the text from afterTextChanged.

The second method directly inserts whitespace characters after the characters that need spacing. This method alters the original text length and content but does not rely on the TextView layer for rendering. It uses TextPaint to draw the text directly, suitable for all scenarios, but does not support dynamic application (injection).

Unresolved Issues

PanguText may conflict with Material components like TextInputEditText, MaterialAutoCompleteTextView, and TextInputLayout when using setHint, as TextView does not account for Span during measurement. This issue is particularly noticeable in single-line text, and there is no solution yet. Use these components cautiously.

Due to the above issue, calculating the width of a TextView with PanguText style using the View.measure method may also result in errors.

PanguText currently cannot handle continuous characters like underlines or strikethroughs in Spanned text, as the lines will break after adding spacing. It may also cause style errors or fail to apply styles correctly to some special characters. For stability, avoid enabling PanguText for very complex rich text or refer to the Personalized Configuration section to set excludePatterns.

Integrate into Existing Projects

Integrating PanguText into your current project is very easy. You don't need to change much code. Choose your preferred method below to complete the integration.

Inject to LayoutInflater

PanguText supports direct injection of LayoutInflater.Factory2 or creating a LayoutInflater.Factory2 instance for the current Activity to take over the entire view layout inflation. This is the recommended integration method, as it allows for non-intrusive and quick integration without modifying any existing layouts.

The following example

class MainActivity : AppCompatActivity() {
+
+    val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        // Inject here.
+        PanguTextFactory2.inject(this)
+        setContentView(binding.root)
+    }
+}
+

Tips

Since LayoutInflater.Factory2 is taken over, recycled layouts like ListView and RecyclerView can also be correctly handled.

After injecting the LayoutInflater instance in the Activity, the following instances attached to the current Context will automatically take effect:

  • Fragment
  • Dialog
  • PopupWindow
  • Toast (foreground only in higher system versions)

Layouts based on RemoteView will not take effect because they are remote objects and do not use the current Context's LayoutInflater for layout inflation.

If you are using ui-component → AppBindingActivityopen in new window in BetterAndroid, you need to slightly modify the current code.

The following example

class MainActivity : AppBindingActivity<ActivityMainBinding>() {
+
+    override fun onPrepareContentView(savedInstanceState: Bundle?): LayoutInflater {
+        val inflater = super.onPrepareContentView(savedInstanceState)
+        // Inject here.
+        PanguTextFactory2.inject(inflater)
+        return inflater
+    }
+  
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        // Your code here.
+    }
+}
+

If your application does not use AppCompatActivity or ViewBinding, don't worry, you can still use the original method.

The following example

class MainActivity : Activity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        // Inject here.
+        PanguTextFactory2.inject(this)
+        setContentView(R.layout.activity_main)
+    }
+}
+

Tips

PanguTextFactory2 can be used not only with Activity but also injected into any existing LayoutInflater instance. However, please inject it before the LayoutInflater instance is used to inflate the layout, otherwise it will not take effect.

Using the Patching Tool

You can use PanguTextPatcher to patch existing View or ViewGroup instances.

Patch the entire root layout, and PanguTextPatcher will automatically patch all TextView instances or their subclasses under the root layout.

The following example

// Assume you have a root layout.
+val root: ViewGroup
+// Patch the root layout.
+PanguTextPatcher.patch(root)
+

Patch a single View, which is of type TextView or a subclass of TextView.

The following example

// Assume this is your TextView.
+val textView: TextView
+// Patch a single View.
+PanguTextPatcher.patch(textView)
+

Notice

When using PanguTextPatcher in recycled layouts such as RecyclerView, ListView, or ViewPager, you need to patch the itemView in onCreateViewHolder or onBindViewHolder, otherwise it will not take effect.

Manual Injection or Text Formatting

PanguText also supports manual injection, allowing you to inject it into the desired TextView or EditText.

The following example

// Assume this is your TextView.
+val textView: TextView
+// Assume this is your EditText.
+val editText: EditText
+// Inject into existing text.
+textView.injectPanguText()
+editText.injectPanguText()
+// Optionally choose whether to inject Hint (default is true).
+textView.injectPanguText(injectHint = false)
+editText.injectPanguText(injectHint = false)
+// Dynamic injection, re-calling setText will automatically take effect.
+textView.injectRealTimePanguText()
+// Dynamic injection mainly targets the input state of EditText.
+editText.injectRealTimePanguText()
+// Optionally choose whether to inject Hint (default is true).
+textView.injectRealTimePanguText(injectHint = false)
+editText.injectRealTimePanguText(injectHint = false)
+

PanguText also extends the setText method of TextView, allowing you to directly set text with PanguText style.

The following example

// Assume this is your TextView.
+val textView: TextView
+// Set text with PanguText style.
+textView.setTextWithPangu("Xiaoming今年16岁")
+// Set Hint with PanguText style.
+textView.setHintWithPangu("输入Xiaoming的年龄")
+

You can also use the PanguText.format method to directly format text.

The following example

// Assume this is your TextView.
+val textView: TextView
+// Format text using SpannableString method.
+// Requires passing the current TextView's Resources and text size.
+// If the input text is already Spannable,
+// it will return the original object without creating a new SpannableString.
+val text = PanguText.format(textView.resources, textView.textSize, "Xiaoming今年16岁")
+// Set text.
+textView.text = text
+// Directly format text using whitespace characters for insertion.
+// This method adds extra whitespace characters " " (HSP) to the text.
+// The result below will output the string "Xiaoming 今年 16 岁".
+// You can also customize the whitespace character at the end of the method.
+val text = PanguText.format("Xiaoming今年16岁")
+// Set text.
+textView.text = text
+

Tips

The injectPanguText, injectRealTimePanguText, setTextWithPangu, setHintWithPangu, and PanguText.format methods support the config parameter. You can refer to the Personalized Configuration section below.

Custom View

PanguText can also be used with custom View. You can extend your View to AppCompatTextView and override the setText method.

The following example

class MyTextView(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs) {
+
+    override fun setText(text: CharSequence?, type: BufferType?) {
+        // Manually inject here.
+        val panguText = text?.let { PanguText.format(resources, textSize, it) }
+        super.setText(panguText, type)
+    }
+}
+

Notice

After injecting PanguText into TextView, if you use android:singleLine="true" in XML layout or TextView.setSingleLine(true) in code along with android:ellipsize="...", this method of setting single-line text may cause unresolvable OBJ characters (truncated by ellipsis) to appear when the text exceeds the screen width, because TextView does not account for Span during measurement, leading to incorrect text width calculation.

The solution is to use android:maxLines="1" in XML layout or TextView.setMaxLines(1) in code instead.

The following example

<TextView
+    android:id="@+id/text"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="这是一段很长很长长长长长长长长长长长长还有English混入的的文本"
+    android:maxLines="1"
+    android:ellipsize="end" />
+

Personalized Configuration

PanguText supports personalized configuration. You can use the global static instance PanguText.globalConfig to get the global configuration or configure it individually.

The following example

// Get global configuration.
+val config = PanguText.globalConfig
+// Enable or disable the feature.
+config.isEnabled = true
+// Process Spanned text.
+// Processing Spanned text is enabled by default, but this feature is experimental.
+// If issues occur, you can disable it. When disabled, Spanned text will return the original text.
+config.isProcessedSpanned = true
+// Whether to automatically re-measure the text width after processing.
+// Note: After [PanguText] injects text and changes the text,
+// the width of [TextView] will not be calculated automatically.
+// At this time, this feature will call [TextView.setText] to re-execute the measurements,
+// which can fix issues in some dynamic layouts (such as `RecyclerView`) where text width changes each time,
+// but may cause performance issues. You can choose to disable this feature.
+// To prevent unnecessary performance overhead,
+// this feature only takes effect on [TextView] with `maxLines` set to 1 or `singleLine`.
+config.isAutoRemeasureText = true
+// Set patterns to exclude during formatting using regular expressions.
+// For example, exclude all URLs.
+config.excludePatterns.add("https?://\\S+".toRegex())
+// For example, exclude emoji placeholders like "[doge]".
+// If you use [ImageSpan] to display emoji images, you can choose to exclude these placeholders.
+config.excludePatterns.add("\\[.*?]".toRegex())
+// Set the spacing ratio for CJK characters.
+// This determines the final layout effect.
+// It is recommended to keep the default ratio and adjust it according to personal preference.
+config.cjkSpacingRatio = 7f
+

Notice

If you integrated using the Inject to LayoutInflater method, configure PanguText.globalConfig before executing PanguTextFactory2.inject(...), otherwise the configuration will not take effect.

You can also pass the config parameter for personalized configuration when manually injecting or formatting text.

The following example

// Assume this is your TextView.
+val textView: TextView
+// Create a new configuration.
+// You can set [copyFromGlobal] to false to not copy from the global configuration.
+val config = PanguTextConfig(copyFromGlobal = false) {
+    excludePatterns.add("https?://\\S+".toRegex())
+    excludePatterns.add("\\[.*?]".toRegex())
+    cjkSpacingRatio = 7f
+}
+// You can also copy and create a new configuration from any configuration.
+val config2 = config.copy {
+    excludePatterns.clear()
+    excludePatterns.add("https?://\\S+".toRegex())
+    excludePatterns.add("\\[.*?]".toRegex())
+    cjkSpacingRatio = 7f
+}
+// Manually inject and configure.
+textView.injectPanguText(config = config2)
+

If you integrated using the Inject to LayoutInflater method, you can use the following attributes in the XML layout declaration of TextView, EditText, or their subclasses for personalized configuration.

  • panguText_enabled corresponds to PanguTextConfig.isEnabled
  • panguText_processedSpanned corresponds to PanguTextConfig.isProcessedSpanned
  • panguText_autoRemeasureText corresponds to PanguTextConfig.isAutoRemeasureText
  • panguText_excludePatterns corresponds to PanguTextConfig.excludePatterns, string array, multiple patterns separated by |@|
  • panguText_cjkSpacingRatio corresponds to PanguTextConfig.cjkSpacingRatio

The following example

<TextView
+    android:id="@+id/text"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="Xiaoming今年16岁"
+    app:panguText_enabled="true"
+    app:panguText_processedSpanned="true"
+    app:panguText_autoRemeasureText="true"
+    app:panguText_excludePatterns="https?://\\S+;\\[.*?]|@|\\[.*?]"
+    app:panguText_cjkSpacingRatio="7.0" />
+

Notice

Due to issues with Android Studio, the above attributes may not have auto-completion hints. Please complete them manually.

Don't forget to add the declaration xmlns:app="http://schemas.android.com/apk/res-auto".

In custom View, you can extend your View to implement the PanguTextView interface to achieve the same functionality. This feature is also effective for the Using the Patching Tool method.

The following example

class MyTextView(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs),
+    PanguTextView {
+
+    override fun configurePanguText(config: PanguTextConfig) {
+        // Configure your [PanguTextConfig].
+    }
+}
+

Notice

The PanguTextView interface takes precedence over attributes used directly in the XML layout. If you use both methods for configuration, the PanguTextView interface configuration will override the XML layout configuration.

Individual configurations will override global configurations, and options not configured will follow the global configuration.

+ + + diff --git a/en/library/compose.html b/en/library/compose.html new file mode 100644 index 0000000..63a2daa --- /dev/null +++ b/en/library/compose.html @@ -0,0 +1,34 @@ + + + + + + + + + Jetpack Compose | Pangu Text + + + + + +

Jetpack Compose

Maven CentralMaven metadata URL

This is the core dependency for Jetpack Compose (multiplatform). When using PanguText in Jetpack Compose, you need to include this module.

This module is currently under development and will be gradually improved in the future.

+ + + diff --git a/images/demo_01.png b/images/demo_01.png new file mode 100644 index 0000000..fd5c639 Binary files /dev/null and b/images/demo_01.png differ diff --git a/images/demo_02.gif b/images/demo_02.gif new file mode 100644 index 0000000..4a933bd Binary files /dev/null and b/images/demo_02.gif differ diff --git a/images/demo_02.mov b/images/demo_02.mov new file mode 100644 index 0000000..a5b7e7c Binary files /dev/null and b/images/demo_02.mov differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..55e4d67 Binary files /dev/null and b/images/logo.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..ec401cb --- /dev/null +++ b/index.html @@ -0,0 +1,34 @@ + + + + + + + + + Pangu Text + + + + + +

Select a language

English 简体中文

+ + + diff --git a/zh-cn/about/about.html b/zh-cn/about/about.html new file mode 100644 index 0000000..283b56a --- /dev/null +++ b/zh-cn/about/about.html @@ -0,0 +1,49 @@ + + + + + + + + + 关于此文档 | Pangu Text + + + + + +

关于此文档

此文档由 VuePress在新窗口中打开 强力驱动。

许可证

Apache-2.0在新窗口中打开

Apache License Version 2.0
+
+Copyright (C) 2019 HighCapable
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+

版权所有 © 2019 HighCapable

+ + + diff --git a/zh-cn/about/changelog.html b/zh-cn/about/changelog.html new file mode 100644 index 0000000..d41b209 --- /dev/null +++ b/zh-cn/about/changelog.html @@ -0,0 +1,34 @@ + + + + + + + + + 更新日志 | Pangu Text + + + + + +

更新日志

这里记录了 PanguText 的版本更新历史。

特别注意

我们只会对最新的 API 版本进行维护,若你正在使用过时的 API 版本则代表你自愿放弃一切维护的可能性。

pangutext-android

1.0.4 | 2025.08.16  最新

  • 在执行 injectPanguText 时排除 TextView 自身设置的 TextWatcher 防止重复触发 doOnTextChanged

1.0.3 | 2025.08.03  过旧

1.0.2 | 2025.03.05  过旧

  • PanguTextFactory2 在注入时新增异常捕获,避免在 View 自身初始化过程中断整个处理过程
  • 移除重复注入的警告日志,现在重复注入 PanguText 将无任何作用产生
  • 新增 PanguTextPatcher,可以使用新的方案注入 PanguText

1.0.1 | 2025.02.11  过旧

  • 修复注入 PanguTextTextView 可能导致测量宽度不正确的问题
  • PanguTextConfig 新增 isAutoRemeasureText,用于控制是否自动重新测量文本宽度 (作用于 TextView 单行文本)

1.0.0 | 2025.02.10  过旧

  • 首个版本提交至 Maven

pangutext-compose

暂未发布。

+ + + diff --git a/zh-cn/about/contacts.html b/zh-cn/about/contacts.html new file mode 100644 index 0000000..3b84057 --- /dev/null +++ b/zh-cn/about/contacts.html @@ -0,0 +1,34 @@ + + + + + + + + + 联系我们 | Pangu Text + + + + + + + + + diff --git a/zh-cn/about/future.html b/zh-cn/about/future.html new file mode 100644 index 0000000..55aaf67 --- /dev/null +++ b/zh-cn/about/future.html @@ -0,0 +1,34 @@ + + + + + + + + + 展望未来 | Pangu Text + + + + + +

展望未来

未来是美好的,也是不确定的,让我们共同期待 PanguText 在未来的发展空间。

未来的计划

这里收录了 PanguText 可能会在后期添加的功能。

SpannableString 的局限性

PanguText 目前在 Android 平台上的主要功能来自 SpannableString,目前尚未完全解决处理复杂的文本样式以及性能开销问题。

Jetpack Compose 计划

PanguText 未来将会支持 Jetpack Compose,并计划采用 AnnotatedString 作为主要的文本处理方式以实现对底层的最小化侵入。

+ + + diff --git a/zh-cn/config/r8-proguard.html b/zh-cn/config/r8-proguard.html new file mode 100644 index 0000000..b388dd4 --- /dev/null +++ b/zh-cn/config/r8-proguard.html @@ -0,0 +1,34 @@ + + + + + + + + + R8 与 Proguard 混淆 | Pangu Text + + + + + + + + + diff --git a/zh-cn/guide/home.html b/zh-cn/guide/home.html new file mode 100644 index 0000000..7f9b418 --- /dev/null +++ b/zh-cn/guide/home.html @@ -0,0 +1,34 @@ + + + + + + + + + 介绍 | Pangu Text + + + + + +

介绍

PanguText 是一个中日韩 (CJK) 与英文单词、半角数字排版的解决方案。

背景

这个项目的起因是因为直到目前为止还没有一套公开的方案能够完美解决中文、日文、韩文与英文之间的排版问题, 正常情况下我们将 CJK (即中日韩) 与英文混排的时候,都会涉及到美观性问题,这算是一个历史遗留问题,全角文字与半角文字之间的书写规范不一样。虽然现在 W3C 规定了 CJK 排版规范, 但是还是仅有部分愿意遵守排版要求的个人或企业选择了这种方案。

目前已知的厂商解决方案如下

  • Apple 全系 (iOS、iPadOS、macOS、tvOS、watchOS) 文本排版解决方案
  • 小米 (HyperOS) 文本排版优化
  • OrginOS 基于字体的文本排版优化

但是这些方案都是封闭的,无法在其他平台上使用,因此我们希望能够提供一套开源的解决方案,能够适应各种场景、侵入性低且更容易集成,让更多的开发者能够使用这个方案来解决文本排版问题。

本项目得以进行的主要来源为 pangu.js在新窗口中打开,它提供了一套 CJK 排版的正则,我们对其加以优化,实现各个平台不需要插入空格字符即可格式化文本排版的效果, 衷心感谢这个项目的开发者提供的方案,我们在这个方案上加以扩展,提供了更多解决方案的可能性。

效果

如你所见,PanguText 的排版方案并不是向 CJK 与英文单词之间插入空格来完成,而是使用每个平台对应的处理方案自动在这些字符之间添加空白间距来达到排版效果以达到最低的侵入性。

应用前 (上)、应用后 (下)

动态应用

PanguText 支持动态应用,它允许你在输入文本的同时动态为每个字符添加空白间距。

开发者的观点

我个人依然不提倡手动为 CJK 和英文字符之间添加空格来达到排版美化效果 (如果软件、系统本身支持这种排版美化方式), 因为空格在不同的字体中的间距也是不一样的,这会造成排版效果出现问题,也会被加入本不应该出现的空格字符,在某些场景下,例如网址、文件名或者带有 “#” 的话题标签,不允许出现这些空格。但是,在一些特殊场景,例如代码的注释中,涉及到代码的说明文档,建议加入空格,因为这些范围内可能不会有排版格式化工具。

还有一点就是,在不同的语言中使用不同的标点符号,切忌全角和半角标点符号混用,如果一定要使用半角标点符号来标记全角文字,在句子未结束时将半角符号向后推进一个空格补全字符空间 (英文也是如此)。

语言要求

推荐使用 Kotlin 作为首选开发语言,本项目完全使用 Kotlin 编写,在部分内容上对 Java 做了兼容处理,但也许无法做到完全兼容。

文档全部的 Demo 示例代码都将使用 Kotlin 进行描述,如果你完全不会使用 Kotlin,那么你将有可能无法获得最佳使用体验。

功能贡献

本项目的维护离不开各位开发者的支持和贡献,目前这个项目处于初期阶段,可能依然存在一些问题或者缺少你需要的功能, 如果可能,欢迎提交 PR 为此项目贡献你认为需要的功能或前往 GitHub Issues在新窗口中打开 向我们提出建议。

+ + + diff --git a/zh-cn/guide/quick-start.html b/zh-cn/guide/quick-start.html new file mode 100644 index 0000000..07291b4 --- /dev/null +++ b/zh-cn/guide/quick-start.html @@ -0,0 +1,61 @@ + + + + + + + + + 快速开始 | Pangu Text + + + + + +

快速开始

集成 PanguText 到你的项目中。

项目要求

项目需要使用 Android StudioIntelliJ IDEA 创建且类型为 Android 或 Kotlin Multiplatform 项目并已集成 Kotlin 环境依赖。

配置存储库

PanguText 的依赖发布在 Maven Central 和我们的公共存储库中,你可以使用如下方式配置存储库。

我们推荐使用 Kotlin DSL 作为 Gradle 构建脚本语言并推荐使用 SweetDependency在新窗口中打开 来管理依赖。

SweetDependency (推荐)

在你的项目 SweetDependency 配置文件中配置存储库。

repositories:
+  google:
+  maven-central:
+  # (可选) 你可以添加此 URL 以使用我们的公共存储库
+  # 当 Sonatype-OSS 发生故障无法发布依赖时,此存储库作为备选进行添加
+  # 详情请前往:https://github.com/HighCapable/maven-repository
+  highcapable-maven-releases:
+    # 中国大陆用户请将下方的 "raw.githubusercontent.com" 修改为 "raw.gitmirror.com"
+    url: https://raw.githubusercontent.com/HighCapable/maven-repository/main/repository/releases
+

传统方式

在你的项目 build.gradle.kts 中配置存储库。

repositories {
+    google()
+    mavenCentral()
+    // (可选) 你可以添加此 URL 以使用我们的公共存储库
+    // 当 Sonatype-OSS 发生故障无法发布依赖时,此存储库作为备选进行添加
+    // 详情请前往:https://github.com/HighCapable/maven-repository
+    // 中国大陆用户请将下方的 "raw.githubusercontent.com" 修改为 "raw.gitmirror.com"
+    maven("https://raw.githubusercontent.com/HighCapable/maven-repository/main/repository/releases")
+}
+

配置 Java 版本

在你的项目 build.gradle.kts 中修改 Kotlin 的 Java 版本为 17 及以上。

android {
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_17
+        targetCompatibility = JavaVersion.VERSION_17
+    }
+    kotlinOptions {
+        jvmTarget = "17"
+    }
+}
+

功能一览

整个项目分为多个模块,Android 平台与 Jetpack Compose (多平台),你可以选择你希望引入的模块作为依赖应用到你的项目中。

你可以点击下方对应的模块前往查看详细的功能介绍。

Demo

你可以在下方找到一些示例,查看对应的演示项目来更好地了解这些功能的运作方式,快速地挑选出你需要的功能。

+ + + diff --git a/zh-cn/index.html b/zh-cn/index.html new file mode 100644 index 0000000..4a61976 --- /dev/null +++ b/zh-cn/index.html @@ -0,0 +1,34 @@ + + + + + + + + + 首页 | Pangu Text + + + + + + + + + diff --git a/zh-cn/library/android.html b/zh-cn/library/android.html new file mode 100644 index 0000000..fee0d3a --- /dev/null +++ b/zh-cn/library/android.html @@ -0,0 +1,200 @@ + + + + + + + + + Android | Pangu Text + + + + + +

Android

Maven CentralMaven metadata URLAndroid Min SDK

这是 Android 平台的核心依赖,在 Android 平台上使用 PanguText 时,你需要引入此模块。

配置依赖

你可以使用如下方式将此模块添加到你的项目中。

SweetDependency (推荐)

在你的项目 SweetDependency 配置文件中添加依赖。

libraries:
+  com.highcapable.pangutext:
+    pangutext-android:
+      version: +
+

在你的项目 build.gradle.kts 中配置依赖。

implementation(com.highcapable.pangutext.pangutext.android)
+

Version Catalog

在你的项目 gradle/libs.versions.toml 中添加依赖。

[versions]
+pangutext-android = "<version>"
+
+[libraries]
+pangutext-android = { module = "com.highcapable.pangutext:pangutext-android", version.ref = "pangutext-android" }
+

在你的项目 build.gradle.kts 中配置依赖。

implementation(libs.pangutext.android)
+

请将 <version> 修改为此文档顶部显示的版本。

传统方式

在你的项目 build.gradle.kts 中配置依赖。

implementation("com.highcapable.pangutext:pangutext-android:<version>")
+

请将 <version> 修改为此文档顶部显示的版本。

功能介绍

你可以 点击这里在新窗口中打开 查看 KDoc。

实现原理

PanguText 在 Android 平台有两种方案对文本进行格式化,一种为 SpannableString (不破坏原始文本长度),另一种则是直接插入空白字符 (破坏原始文本长度)。

第一种方案为 SpannableString,它会在需要增加间距的字符的前一个字符后增加应用了间距的 Span 来实现文本在样式上的改变,而不实际改变字符串的内容,最后交由 TextView 层完成渲染 (或手动使用 TextPaint 基于 Spanned 做布局样式处理),实现无侵入式为文本设置样式。

第一种方案同样支持直接处理已经应用了样式的文本 (Spanned),例如通过 Html.fromHtml 创建的文本,但是目前尚处于实验性阶段,可能仍然会出现非预期样式错误问题, 你可以参考下方的 个性化配置 选择禁用它。

动态应用 (注入) 功能主要针对 EditText 的输入状态,它会为 EditText 设置一个自定义的 TextWatcher 来监听输入状态,当输入状态发生变化时,从 afterTextChanged 中获取 Editable 并进行格式化。

第二种方案则是直接插入空白字符,它会直接在需要增加间距的字符后插入空白字符,这种方案会破坏原始文本的长度并且会改变文本内容自身, 但是可以不依赖于 TextView 层完成渲染,直接使用 TextPaint 绘制文本即可,适用于所有场景,但不支持动态应用 (注入)

尚未解决的问题

PanguText 可能会与 Material 组件 TextInputEditTextMaterialAutoCompleteTextViewTextInputLayout 结合时在 setHint 效果上产生冲突, 因为 TextView 不会在测量时计算文本中的 Span,在单行文本中此类问题尤为明显,暂时还没有解决方案,请谨慎配合此类组件使用。

受制于上述问题,通过 View.measure 方法计算包含了 PanguText 风格的 TextView 宽度时也可能会出现错误。

PanguText 目前不能处理 Spanned 文本中的下划线、删除线这种连续的字符,添加空白间距后线条会中断, 并且它可能会在一些特殊字符上发生样式错误或样式没有被正确应用,为了稳定性考虑请尽量不要对非常复杂的富文本启用 PanguText 或参考下方的 个性化配置 设置 excludePatterns

集成到现有项目

PanguText 集成到你的当前项目中非常容易,你不需要改动过多代码,挑选以下你喜欢的方案进行,即可完成集成。

注入布局装载器 (LayoutInflater)

PanguText 支持直接注入 LayoutInflater.Factory2 或为当前 Activity 创建 LayoutInflater.Factory2 实例以接管整个视图, 这是推荐的集成方案,这种方式不需要修改任何现有布局即可实现无侵入式快速集成。

示例如下

class MainActivity : AppCompactActivity() {
+
+    val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        // 在这里注入
+        PanguTextFactory2.inject(this)
+        setContentView(binding.root)
+    }
+}
+

小提示

由于接管了 LayoutInflater.Factory2,所以包括类似 ListViewRecyclerView 的回收式布局也能被正确接管。

注入 Activity 中的 LayoutInflater 实例后,以下附属于当前 Context 的实例都会自动生效。

  • Fragment
  • Dialog
  • PopupWindow
  • Toast (在高版本系统中仅前台)

基于 RemoteView 的布局将无法生效,因为它们是远程对象,不会使用当前 ContextLayoutInflater 进行布局装载。

如果你正在使用 BetterAndroid 中的 ui-compoment → AppBindingActivity在新窗口中打开,你需要稍微改动当前代码。

示例如下

class MainActivity : AppBindingActivity<ActivityMainBinding>() {
+
+   override fun onPrepareContentView(savedInstanceState: Bundle?): LayoutInflater {
+       val inflater = super.onPrepareContentView(savedInstanceState)
+       // 在这里注入
+       PanguTextFactory2.inject(inflater)
+       return inflater
+   }
+
+   override fun onCreate(savedInstanceState: Bundle?) {
+       super.onCreate(savedInstanceState)
+       // Your code here.
+   }
+}
+

如果你的应用程序没有使用 AppCompatActivity 也没有使用 ViewBinding,没有关系,你依然可以使用最初的方案进行。

示例如下

class MainActivity : Activity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        // 在这里注入
+        PanguTextFactory2.inject(this)
+        setContentView(R.layout.activity_main)
+    }
+}
+

小提示

PanguTextFactory2 除了可以配合 Activity 使用,它还支持注入到任何现有的 LayoutInflater 实例中,但请在 LayoutInflater 实例被用于装载布局前进行注入,否则将无法生效。

使用修补工具

你可以使用 PanguTextPatcher 修补现有的 ViewViewGroup 实例。

修补整个根布局,PanguTextPatcher 会自动修补根布局下的所有 TextView 或继承于其的组件。

示例如下

// 假设你有一个根布局
+val root: ViewGroup
+// 修补根布局
+PanguTextPatcher.patch(root)
+

修补单个 View,类型为 TextView 或继承于 TextView 的组件。

示例如下

// 假设这就是你的 TextView
+val textView: TextView
+// 修补单个 View
+PanguTextPatcher.patch(textView)
+

注意

RecyclerViewListViewViewPager 等回收式布局中使用 PanguTextPatcher 时,你需要在 onCreateViewHolderonBindViewHolder 中获取到 itemView 后进行修补,否则不会生效。

手动注入或格式化文本

PanguText 同样支持手动注入,你可以在需要的 TextViewEditText 上手动进行注入。

示例如下

// 假设这就是你的 TextView
+val textView: TextView
+// 假设这就是你的 EditText
+val editText: EditText
+// 注入到现有文本
+textView.injectPanguText()
+editText.injectPanguText()
+// 可以选择是否同时注入 Hint (默认是)
+textView.injectPanguText(injectHint = false)
+editText.injectPanguText(injectHint = false)
+// 动态注入,重新调用 setText 也会自动生效
+textView.injectRealTimePanguText()
+// 动态注入主要针对于 EditText 的输入状态
+editText.injectRealTimePanguText()
+// 同样可以选择是否同时注入 Hint (默认是)
+textView.injectRealTimePanguText(injectHint = false)
+editText.injectRealTimePanguText(injectHint = false)
+

PanguText 还对 TextViewsetText 方法进行了扩展,你可以使用如下方式直接设置带有 PanugText 样式的文本。

示例如下

// 假设这就是你的 TextView
+val textView: TextView
+// 设置带有 PanguText 样式的文本
+textView.setTextWithPangu("Xiaoming今年16岁")
+// 设置带有 PanguText 样式的 Hint
+textView.setHintWithPangu("输入Xiaoming的年龄")
+

你还可以使用 PanguText.format 方法直接格式化文本。

示例如下

// 假设这就是你的 TextView
+val textView: TextView
+// 使用 SpannableString 方案格式化文本
+// 需要传入当前 TextView 的 Resources 以及字体大小
+// 如果传入的文本自身为 Spannable 类型,则不会创建新的 SpannableString,而是返回原始对象
+val text = PanguText.format(textView.resources, textView.textSize, "Xiaoming今年16岁")
+// 设置文本
+textView.text = text
+// 直接使用空白字符以插入破坏的方式格式化文本
+// 这个方案会为文本增加额外的空白字符 " " (HSP)
+// 下方的结果会输出字符串 "Xiaoming 今年 16 岁"
+// 你也可以在方法末位自定义要使用的空白字符
+val text = PanguText.format("Xiaoming今年16岁")
+// 设置文本
+textView.text = text
+

小提示

injectPanguTextinjectRealTimePanguTextsetTextWithPangusetHintWithPanguPanguText.format 方法支持 config 参数,你可以参考下方的 个性化配置

自定义 View

PanguText 还可以配合自定义 View 进行使用,你可以将你的 View 继承到 AppCompatTextView 并重写 setText 方法。

示例如下

class MyTextView(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs) {
+
+    override fun setText(text: CharSequence?, type: BufferType?) {
+        // 在这里手动进行注入
+        val panguText = text?.let { PanguText.format(resources, textSize, it) }
+        super.setText(panguText, type)
+    }
+}
+

注意

TextView 在注入 PanguText 后,如果你在 XML 布局中使用了 android:singleLine="true" 或在代码中使用了 TextView.setSingleLine(true) 并且配合 android:elipsize="...", 那么这种方式设置单行文本可能会造成文本超出屏幕后其中会中显示出无法解析的 OBJ 字符 (被省略号截断),因为 TextView 不会在测量时计算文本中的 Span,这会导致文本宽度计算错误。 解决方案为在 XML 布局中使用 android:maxLines="1" 或在代码中使用 TextView.setMaxLines(1) 来代替。

示例如下

<TextView
+    android:id="@+id/text"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="这是一段很长很长长长长长长长长长长长长还有English混入的的文本"
+    android:maxLines="1"
+    android:ellipsize="end" />
+

个性化配置

PanguText 支持个性化配置,你可以使用全局静态实例 PanguText.globalConfig 获取全局配置,或单独进行配置。

示例如下

// 获取全局配置
+val config = PanguText.globalConfig
+// 开关,禁用将使所有功能失效
+config.isEnabled = true
+// 处理 Spanned 文本
+// Spanned 文本处理默认启用,但此功能尚处于实验性阶段,
+// 如果发生问题你可以选择禁用,禁用后遇到 Spanned 文本将返回原始文本
+config.isProcessedSpanned = true
+// 是否要在处理后自动重新测量文本宽度
+// 注意:[PanguText] 注入文本并更改文本后,[TextView] 的宽度将不会自动计算
+// 目前,此功能将调用 [TextView.setText] 重新执行测量结果,
+// 该测量可以在某些动态布局 (例如 `RecyclerView`) 中每次修复文本宽度,
+// 但可能会导致性能问题,你可以选择禁用此功能
+// 为了防止不必要的性能开销,此功能仅在 `maxlines` 设置为 1 或 `singleLine` 的 [TextView] 上生效
+config.isAutoRemeasureText = true
+// 设置在格式化过程中以正则形式定义需要排除的内容
+// 例如排除全部 URL
+config.excludePatterns.add("https?://\\S+".toRegex())
+// 例如排除类似 "[doge]" 的 emoji 占位符,
+// 如果你需要使用 [ImageSpan] 显示 emoji 图片,你可以选择排除这些占位符
+config.excludePatterns.add("\\[.*?]".toRegex())
+// 设置 CJK 空白占位间距比例
+// 这会决定最终的排版效果,建议保持默认比例,然后再以此跟随个人喜好进行调整
+config.cjkSpacingRatio = 7f
+

注意

如果你使用了 注入布局装载器 的方案进行集成,请在 PanguTextFactory2.inject(...) 执行前配置 PanguText.globalConfig,否则配置将无法生效。

你还可以在手动注入或格式化文本时传入 config 参数以进行个性化配置。

示例如下

// 假设这就是你的 TextView
+val textView: TextView
+// 创建一个新配置
+// 你可以设置 [copyFromGlobal] 为 false 来不从全局配置中复制配置
+val config = PanguTextConfig(copyFromGlobal = false) {
+    excludePatterns.add("https?://\\S+".toRegex())
+    excludePatterns.add("\\[.*?]".toRegex())
+    cjkSpacingRatio = 7f
+}
+// 你还可以从任意一个配置中复制并创建新配置
+val config2 = config.copy {
+    excludePatterns.clear()
+    excludePatterns.add("https?://\\S+".toRegex())
+    excludePatterns.add("\\[.*?]".toRegex())
+    cjkSpacingRatio = 7f
+}
+// 手动注入并配置
+textView.injectPanguText(config = config2)
+

如果你使用了 注入布局装载器 的方案进行集成,你可以在 TextViewEditText 或继承于它们的 XML 布局声明中使用以下属性来进行个性化配置。

  • panguText_enabled 对应 PanguTextConfig.isEnabled
  • panguText_processedSpanned 对应 PanguTextConfig.isProcessedSpanned
  • panguText_autoRemeasureText 对应 PanguTextConfig.isAutoRemeasureText
  • panguText_excludePatterns 对应 PanguTextConfig.excludePatterns,字符串数组,多个使用 |@| 分隔
  • panguText_cjkSpacingRatio 对应 PanguTextConfig.cjkSpacingRatio

示例如下

<TextView
+    android:id="@+id/text"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="Xiaoming今年16岁"
+    app:panguText_enabled="true"
+    app:panguText_processedSpanned="true"
+    app:panguText_autoRemeasureText="true"
+    app:panguText_excludePatterns="https?://\\S+;\\[.*?]|@|\\[.*?]"
+    app:panguText_cjkSpacingRatio="7.0" />
+

注意

由于 Android Studio 的问题,上述属性可能不会有补全提示,请自行补全。

不要忘记加入声明 xmlns:app="http://schemas.android.com/apk/res-auto"

在自定义 View 中,你可以将你的 View 继承于 PanguTextView 接口以同样实现上述功能,此功能对 使用修补工具 方案同样有效。

示例如下

class MyTextView(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs),
+    PanguTextView {
+
+    override fun configurePanguText(config: PanguTextConfig) {
+        // 配置你的 [PanguTextConfig]
+    }
+}
+

注意

PanguTextView 接口的优先级将高于直接在 XML 布局中使用的属性,如果你同时使用了这两种方式进行配置,PanguTextView 接口的配置将覆盖 XML 布局中的配置。

单独配置将覆盖全局配置,未配置的选项将跟随全局配置。

+ + + diff --git a/zh-cn/library/compose.html b/zh-cn/library/compose.html new file mode 100644 index 0000000..7ff1273 --- /dev/null +++ b/zh-cn/library/compose.html @@ -0,0 +1,34 @@ + + + + + + + + + Jetpack Compose | Pangu Text + + + + + + + + +