react-native-enriched-markdown 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -37
- package/ReactNativeEnrichedMarkdown.podspec +44 -23
- package/android/build.gradle +110 -11
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +1 -1
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +4 -0
- package/cpp/highlight/code_highlight_podspec.rb +109 -16
- package/docs/BREAKING_CHANGES.md +87 -0
- package/docs/CODE_HIGHLIGHT.md +26 -50
- package/docs/LATEX_MATH.md +30 -48
- package/docs/NATIVE_ASSETS.md +39 -13
- package/package.json +6 -14
- package/postinstall.mjs +29 -5
- package/app.plugin.js +0 -2
- package/plugin/build/withAndroidCodeHighlight.js +0 -32
- package/plugin/build/withAndroidMath.js +0 -19
- package/plugin/build/withIosCodeHighlight.js +0 -37
- package/plugin/build/withIosMath.js +0 -28
- package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -16
- package/plugin/src/withAndroidCodeHighlight.ts +0 -38
- package/plugin/src/withAndroidMath.ts +0 -24
- package/plugin/src/withIosCodeHighlight.ts +0 -45
- package/plugin/src/withIosMath.ts +0 -35
- package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -28
- package/plugin/tsconfig.build.json +0 -16
package/README.md
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
<
|
|
1
|
+
<picture>
|
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/b1efabc5-37df-4ddc-8fbb-6f587fdcb5e6">
|
|
3
|
+
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/eb844f3b-4b63-4327-bf5e-569e4573dedc">
|
|
4
|
+
<img alt="Enriched Markdown by Software Mansion" src="https://github.com/user-attachments/assets/b1efabc5-37df-4ddc-8fbb-6f587fdcb5e6">
|
|
5
|
+
</picture>
|
|
2
6
|
<a href="https://swm-delivery.com/www/delivery/ck-slug.php?zoneid=zone-gh-react-native-enriched-1&n=1"><img src="https://swm-delivery.com/www/images/zone-gh-react-native-enriched-1?n=1" /></a>
|
|
3
7
|
<a href="https://swm-delivery.com/www/delivery/ck-slug.php?zoneid=zone-gh-react-native-enriched-2&n=1"><img src="https://swm-delivery.com/www/images/zone-gh-react-native-enriched-2?n=1" /></a>
|
|
4
8
|
<a href="https://swm-delivery.com/www/delivery/ck-slug.php?zoneid=zone-gh-react-native-enriched-3&n=1"><img src="https://swm-delivery.com/www/images/zone-gh-react-native-enriched-3?n=1" /></a>
|
|
@@ -15,11 +19,11 @@
|
|
|
15
19
|
- 📐 CommonMark standard compliant
|
|
16
20
|
- 📊 GitHub Flavored Markdown (GFM)
|
|
17
21
|
- 🧮 LaTeX math rendering (block `$$...$$` with `flavor="github"`, inline `$...$` in all flavors)
|
|
18
|
-
- 🔀 [Markdown Streaming](docs/MARKDOWN_STREAMING.md) support (via [react-native-streamdown](https://github.com/software-mansion-labs/react-native-streamdown))
|
|
22
|
+
- 🔀 [Markdown Streaming](../../docs/MARKDOWN_STREAMING.md) support (via [react-native-streamdown](https://github.com/software-mansion-labs/react-native-streamdown))
|
|
19
23
|
- 🎨 Fully customizable styles for all elements
|
|
20
24
|
- ✨ Text selection and copy support
|
|
21
25
|
- 📌 Custom text selection context menu items
|
|
22
|
-
- 🔗 Interactive link handling with [per-URL-pattern styling](docs/MENTIONS.md#link-variants-styling) (`linkVariants`)
|
|
26
|
+
- 🔗 Interactive link handling with [per-URL-pattern styling](../../docs/MENTIONS.md#link-variants-styling) (`linkVariants`)
|
|
23
27
|
- 👤 Renders mentions as styled links (compatible with `EnrichedMarkdownTextInput` mention output)
|
|
24
28
|
- 🙈 Spoiler text with animated particle overlay and tap-to-reveal
|
|
25
29
|
- 🖼️ Native image interactions (iOS: Copy, Save to Camera Roll)
|
|
@@ -36,7 +40,7 @@
|
|
|
36
40
|
- 🔗 Auto-link detection with customizable regex
|
|
37
41
|
- 🔄 Smart copy/paste with Markdown preservation
|
|
38
42
|
- 🎨 Customizable bold, italic, and link colors
|
|
39
|
-
- 👤 [Mentions](docs/MENTIONS.md) with configurable indicators, suggestion lifecycle events, and per-pattern link styling
|
|
43
|
+
- 👤 [Mentions](../../docs/MENTIONS.md) with configurable indicators, suggestion lifecycle events, and per-pattern link styling
|
|
40
44
|
|
|
41
45
|
Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues.
|
|
42
46
|
We can help you build your next dream product –
|
|
@@ -46,30 +50,30 @@ We can help you build your next dream product –
|
|
|
46
50
|
|
|
47
51
|
- [Prerequisites](#prerequisites)
|
|
48
52
|
- [Installation](#installation)
|
|
49
|
-
- [Native assets (install-time download)](docs/NATIVE_ASSETS.md)
|
|
53
|
+
- [Native assets (install-time download)](../../docs/NATIVE_ASSETS.md)
|
|
50
54
|
- [EnrichedMarkdownText](#enrichedmarkdowntext-1)
|
|
51
|
-
- [Usage](docs/TEXT.md#usage)
|
|
52
|
-
- [Supported Markdown Elements](docs/TEXT.md#supported-markdown-elements)
|
|
53
|
-
- [Copy Options](docs/TEXT.md#copy-options)
|
|
54
|
-
- [Accessibility](docs/TEXT.md#accessibility)
|
|
55
|
-
- [RTL Support](docs/TEXT.md#rtl-support)
|
|
56
|
-
- [Customizing Styles](docs/TEXT.md#customizing-styles)
|
|
57
|
-
- [LaTeX Math](docs/LATEX_MATH.md)
|
|
58
|
-
- [Image Caching](docs/IMAGE_CACHING.md)
|
|
59
|
-
- [Markdown Streaming](docs/MARKDOWN_STREAMING.md)
|
|
55
|
+
- [Usage](../../docs/TEXT.md#usage)
|
|
56
|
+
- [Supported Markdown Elements](../../docs/TEXT.md#supported-markdown-elements)
|
|
57
|
+
- [Copy Options](../../docs/TEXT.md#copy-options)
|
|
58
|
+
- [Accessibility](../../docs/TEXT.md#accessibility)
|
|
59
|
+
- [RTL Support](../../docs/TEXT.md#rtl-support)
|
|
60
|
+
- [Customizing Styles](../../docs/TEXT.md#customizing-styles)
|
|
61
|
+
- [LaTeX Math](../../docs/LATEX_MATH.md)
|
|
62
|
+
- [Image Caching](../../docs/IMAGE_CACHING.md)
|
|
63
|
+
- [Markdown Streaming](../../docs/MARKDOWN_STREAMING.md)
|
|
60
64
|
- [EnrichedMarkdownTextInput](#enrichedmarkdowntextinput-1)
|
|
61
|
-
- [Usage](docs/INPUT.md#usage)
|
|
62
|
-
- [Inline Styles](docs/INPUT.md#inline-styles)
|
|
63
|
-
- [Links](docs/INPUT.md#links)
|
|
64
|
-
- [Auto-Link Detection](docs/INPUT.md#auto-link-detection)
|
|
65
|
-
- [Mentions](docs/MENTIONS.md)
|
|
66
|
-
- [Style Detection](docs/INPUT.md#style-detection)
|
|
67
|
-
- [Other Events](docs/INPUT.md#other-events)
|
|
68
|
-
- [Customizing Styles](docs/INPUT.md#customizing-enrichedmarkdowntextinput--styles)
|
|
65
|
+
- [Usage](../../docs/INPUT.md#usage)
|
|
66
|
+
- [Inline Styles](../../docs/INPUT.md#inline-styles)
|
|
67
|
+
- [Links](../../docs/INPUT.md#links)
|
|
68
|
+
- [Auto-Link Detection](../../docs/INPUT.md#auto-link-detection)
|
|
69
|
+
- [Mentions](../../docs/MENTIONS.md)
|
|
70
|
+
- [Style Detection](../../docs/INPUT.md#style-detection)
|
|
71
|
+
- [Other Events](../../docs/INPUT.md#other-events)
|
|
72
|
+
- [Customizing Styles](../../docs/INPUT.md#customizing-enrichedmarkdowntextinput--styles)
|
|
69
73
|
- [API Reference](#api-reference)
|
|
70
|
-
- [Testing with Jest](docs/TESTING.md)
|
|
71
|
-
- [Web Support](docs/WEB.md)
|
|
72
|
-
- [macOS Support](docs/MACOS.md)
|
|
74
|
+
- [Testing with Jest](../../docs/TESTING.md)
|
|
75
|
+
- [Web Support](../../docs/WEB.md)
|
|
76
|
+
- [macOS Support](../../docs/MACOS.md)
|
|
73
77
|
- [Compatibility Table](#compatibility-table)
|
|
74
78
|
- [Contributing](#contributing)
|
|
75
79
|
- [Future Plans](#future-plans)
|
|
@@ -102,7 +106,7 @@ npm install katex
|
|
|
102
106
|
yarn add katex
|
|
103
107
|
```
|
|
104
108
|
|
|
105
|
-
See [Web Support](docs/WEB.md) for full setup details, supported features, and prop behaviour.
|
|
109
|
+
See [Web Support](../../docs/WEB.md) for full setup details, supported features, and prop behaviour.
|
|
106
110
|
|
|
107
111
|
### Bare React Native app (iOS / Android)
|
|
108
112
|
|
|
@@ -126,9 +130,55 @@ yarn add react-native-enriched-markdown
|
|
|
126
130
|
> and iOS LaTeX math (kept out of the npm tarball to keep it ~1 MB). This needs network access to
|
|
127
131
|
> `registry.npmjs.org` and `github.com`. If you install offline, with `--ignore-scripts`, or with
|
|
128
132
|
> **pnpm** (which blocks dependency scripts by default), see
|
|
129
|
-
> [Native assets](docs/NATIVE_ASSETS.md) for how to restore them.
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
> [Native assets](../../docs/NATIVE_ASSETS.md) for how to restore them.
|
|
134
|
+
|
|
135
|
+
#### Configuration
|
|
136
|
+
|
|
137
|
+
Add an `"enriched-markdown"` block to your app's `package.json` to configure which features are enabled:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"enriched-markdown": {
|
|
142
|
+
"enableCodeHighlight": true,
|
|
143
|
+
"enableMath": true,
|
|
144
|
+
"codeHighlightLanguages": ["javascript", "typescript", "python", "swift", "kotlin"]
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
| Key | Type | Default | Description |
|
|
150
|
+
|---|---|---|---|
|
|
151
|
+
| `enableCodeHighlight` | `boolean` | `true` | Download and compile tree-sitter grammars for syntax highlighting |
|
|
152
|
+
| `enableMath` | `boolean` | `true` | Download RaTeX for LaTeX math rendering (iOS) and include the Maven dependency (Android) |
|
|
153
|
+
| `codeHighlightLanguages` | `string[]` | all default grammars | Subset of languages to compile (reduces binary size). Ignored when `enableCodeHighlight` is `false`; an empty array `[]` compiles none (same as disabling). |
|
|
154
|
+
|
|
155
|
+
Your app's `package.json` is the single source of truth. `postinstall` reads it to decide
|
|
156
|
+
what to **download** into `node_modules`, and the native build (iOS podspec / Android
|
|
157
|
+
`build.gradle`) reads it directly to decide what to **compile and link** — no Podfile ENV
|
|
158
|
+
vars or `gradle.properties` edits needed. Changing a value takes effect on your next
|
|
159
|
+
`pod install` / native rebuild; **enabling** a feature that was off also needs a reinstall
|
|
160
|
+
(`npm install` / `npm rebuild react-native-enriched-markdown`) so its assets get downloaded.
|
|
161
|
+
|
|
162
|
+
> [!IMPORTANT]
|
|
163
|
+
> **iOS applies config at `pod install`, not at build time.** After editing the `enriched-markdown`
|
|
164
|
+
> block, run `pod install` (a plain `run-ios` reuses the previously resolved pod). When **disabling** a
|
|
165
|
+
> feature that was already compiled in — or narrowing `codeHighlightLanguages` — also do a clean build
|
|
166
|
+
> (`Product > Clean Build Folder`), since Xcode's incremental build can link a stale pod library.
|
|
167
|
+
> Android reconfigures on every build and needs neither step.
|
|
168
|
+
|
|
169
|
+
> [!TIP]
|
|
170
|
+
> If you don't use a feature, disabling it skips the download **and** excludes it from the native build.
|
|
171
|
+
> See [Skipping the download](../../docs/NATIVE_ASSETS.md#skipping-the-download-opt-out) for details.
|
|
172
|
+
|
|
173
|
+
> [!NOTE]
|
|
174
|
+
> **Monorepos:** the native build reads the **app's** `package.json` (the one next to
|
|
175
|
+
> `ios/`/`android/`), so each app can enable/disable features independently. The download
|
|
176
|
+
> opt-out is resolved where you run the install — usually the workspace root — so to skip a
|
|
177
|
+
> download entirely, put the opt-out in the **root** `package.json`.
|
|
178
|
+
|
|
179
|
+
> [!NOTE]
|
|
180
|
+
> Migrating from the Expo config plugin or the `ENV` / `gradle.properties` build flags? See
|
|
181
|
+
> [Breaking changes](../../docs/BREAKING_CHANGES.md).
|
|
132
182
|
|
|
133
183
|
#### 2. Install iOS / macOS dependencies
|
|
134
184
|
|
|
@@ -163,7 +213,7 @@ npx expo prebuild
|
|
|
163
213
|
|
|
164
214
|
> [!NOTE]
|
|
165
215
|
> `npx expo install` runs the same `postinstall` asset download described under
|
|
166
|
-
> [Native assets](docs/NATIVE_ASSETS.md); it needs network access and does not work with Yarn PnP.
|
|
216
|
+
> [Native assets](../../docs/NATIVE_ASSETS.md); it needs network access and does not work with Yarn PnP.
|
|
167
217
|
|
|
168
218
|
> [!IMPORTANT]
|
|
169
219
|
> **iOS: Save to Camera Roll**
|
|
@@ -177,23 +227,23 @@ npx expo prebuild
|
|
|
177
227
|
|
|
178
228
|
## EnrichedMarkdownText
|
|
179
229
|
|
|
180
|
-
See [EnrichedMarkdownText](docs/TEXT.md) for detailed documentation on usage examples, GFM tables, task lists, link handling, supported elements, copy options, accessibility, RTL support, and customizing styles. Mentions created by `EnrichedMarkdownTextInput` render as styled links — use [`linkVariants`](docs/MENTIONS.md#link-variants-styling) to customize their appearance.
|
|
230
|
+
See [EnrichedMarkdownText](../../docs/TEXT.md) for detailed documentation on usage examples, GFM tables, task lists, link handling, supported elements, copy options, accessibility, RTL support, and customizing styles. Mentions created by `EnrichedMarkdownTextInput` render as styled links — use [`linkVariants`](../../docs/MENTIONS.md#link-variants-styling) to customize their appearance.
|
|
181
231
|
|
|
182
232
|
## EnrichedMarkdownTextInput
|
|
183
233
|
|
|
184
|
-
See [EnrichedMarkdownTextInput](docs/INPUT.md) for detailed documentation on usage examples, inline styles, links, style detection, events, and customizing styles.
|
|
234
|
+
See [EnrichedMarkdownTextInput](../../docs/INPUT.md) for detailed documentation on usage examples, inline styles, links, style detection, events, and customizing styles.
|
|
185
235
|
|
|
186
236
|
## API Reference
|
|
187
237
|
|
|
188
|
-
See the [API Reference](docs/API_REFERENCE.md) for a detailed overview of all the props, methods, and events available.
|
|
238
|
+
See the [API Reference](../../docs/API_REFERENCE.md) for a detailed overview of all the props, methods, and events available.
|
|
189
239
|
|
|
190
240
|
## Web Support
|
|
191
241
|
|
|
192
|
-
See [Web Support](docs/WEB.md) for details on supported features, web-specific prop behaviour, and known limitations.
|
|
242
|
+
See [Web Support](../../docs/WEB.md) for details on supported features, web-specific prop behaviour, and known limitations.
|
|
193
243
|
|
|
194
244
|
## macOS Support
|
|
195
245
|
|
|
196
|
-
`react-native-enriched-markdown` supports macOS via [react-native-macos](https://github.com/microsoft/react-native-macos). See [macOS Support](docs/MACOS.md) for details on macOS-specific features, known limitations, and the example app.
|
|
246
|
+
`react-native-enriched-markdown` supports macOS via [react-native-macos](https://github.com/microsoft/react-native-macos). See [macOS Support](../../docs/MACOS.md) for details on macOS-specific features, known limitations, and the example app.
|
|
197
247
|
|
|
198
248
|
## Future Plans
|
|
199
249
|
|
|
@@ -218,11 +268,11 @@ We're actively working on expanding the capabilities of `react-native-enriched-m
|
|
|
218
268
|
|
|
219
269
|
## Contributing
|
|
220
270
|
|
|
221
|
-
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
271
|
+
See the [contributing guide](../../CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
222
272
|
|
|
223
273
|
## License
|
|
224
274
|
|
|
225
|
-
`react-native-enriched-markdown` library is licensed under [The MIT License](
|
|
275
|
+
`react-native-enriched-markdown` library is licensed under [The MIT License](../../LICENSE).
|
|
226
276
|
|
|
227
277
|
---
|
|
228
278
|
|
|
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
|
|
|
19
19
|
s.authors = package["author"]
|
|
20
20
|
|
|
21
21
|
s.platforms = { :ios => min_ios_version_supported, :osx => '14.0' }
|
|
22
|
-
s.source = { :git => "https://github.com/software-mansion/
|
|
22
|
+
s.source = { :git => "https://github.com/software-mansion/enriched-markdown.git", :tag => "#{s.version}" }
|
|
23
23
|
|
|
24
24
|
if monorepo
|
|
25
25
|
s.private_header_files = "ios/**/*.h"
|
|
@@ -36,19 +36,49 @@ Pod::Spec.new do |s|
|
|
|
36
36
|
# links under CocoaPods default static linkage and needs neither `use_frameworks!` nor
|
|
37
37
|
# SPM interop.
|
|
38
38
|
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
# ENV['ENRICHED_MARKDOWN_ENABLE_MATH'] = '0' in your Podfile.
|
|
39
|
+
# The app package.json "enriched-markdown" block is the source of truth; ENV is a
|
|
40
|
+
# deprecated fallback. `math_explicit` tracks an active opt-in (vs the implicit
|
|
41
|
+
# default), which decides the missing-framework behavior below.
|
|
42
|
+
config = EnrichedMarkdownConfig.consumer_config
|
|
44
43
|
ratex_present = File.directory?(File.join(__dir__, 'ios/vendor/RaTeX.xcframework'))
|
|
45
44
|
math_flag = ENV['ENRICHED_MARKDOWN_ENABLE_MATH']
|
|
46
|
-
|
|
47
|
-
if
|
|
48
|
-
|
|
45
|
+
|
|
46
|
+
if config.key?('enableMath')
|
|
47
|
+
math_requested = config['enableMath'] != false
|
|
48
|
+
math_explicit = math_requested
|
|
49
|
+
if math_flag
|
|
50
|
+
EnrichedMarkdownConfig.warn_once(:math_env, '[ReactNativeEnrichedMarkdown] DEPRECATED: ENV[\'ENRICHED_MARKDOWN_ENABLE_MATH\'] ' \
|
|
51
|
+
'is ignored when "enriched-markdown".enableMath is set in your package.json.')
|
|
52
|
+
end
|
|
53
|
+
elsif math_flag
|
|
54
|
+
EnrichedMarkdownConfig.warn_once(:math_env, '[ReactNativeEnrichedMarkdown] DEPRECATED: ENV[\'ENRICHED_MARKDOWN_ENABLE_MATH\'] ' \
|
|
55
|
+
'will be removed in a future version. Configure via "enriched-markdown".enableMath in your package.json instead.')
|
|
56
|
+
math_requested = math_flag == '1'
|
|
57
|
+
math_explicit = math_requested
|
|
58
|
+
else
|
|
59
|
+
math_requested = true
|
|
60
|
+
math_explicit = false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# RaTeX is downloaded at postinstall and kept out of the tarball. Reconcile the
|
|
64
|
+
# request with the vendored framework: an explicit opt-in with the framework missing
|
|
65
|
+
# fails loud; on by default but missing (a partial/failed download, or a monorepo root
|
|
66
|
+
# opt-out) falls back to a clean build without math.
|
|
67
|
+
enable_math = math_requested && ratex_present
|
|
68
|
+
if !math_requested
|
|
69
|
+
EnrichedMarkdownConfig.warn_once(:math_disabled, '[ReactNativeEnrichedMarkdown] LaTeX math disabled via ' \
|
|
70
|
+
'"enriched-markdown".enableMath = false in your app package.json.')
|
|
71
|
+
elsif !ratex_present
|
|
72
|
+
if math_explicit
|
|
73
|
+
raise '[ReactNativeEnrichedMarkdown] LaTeX math is enabled but the vendored RaTeX ' \
|
|
74
|
+
'XCFramework is missing at ios/vendor/RaTeX.xcframework. Reinstall to fetch it: ' \
|
|
75
|
+
'`npm rebuild react-native-enriched-markdown`. ' \
|
|
76
|
+
'To disable math, set "enriched-markdown".enableMath = false in your app package.json. ' \
|
|
77
|
+
'Troubleshooting: https://github.com/software-mansion/enriched-markdown/blob/main/docs/NATIVE_ASSETS.md'
|
|
78
|
+
end
|
|
79
|
+
EnrichedMarkdownConfig.warn_once(:math_disabled, '[ReactNativeEnrichedMarkdown] LaTeX math disabled: the vendored RaTeX ' \
|
|
49
80
|
'XCFramework was not found at ios/vendor/RaTeX.xcframework. If this is unintended, re-run ' \
|
|
50
|
-
'`node node_modules/react-native-enriched-markdown/postinstall.mjs
|
|
51
|
-
"(or set ENV['ENRICHED_MARKDOWN_ENABLE_MATH'] = '1' in your Podfile)."
|
|
81
|
+
'`node node_modules/react-native-enriched-markdown/postinstall.mjs`.')
|
|
52
82
|
end
|
|
53
83
|
|
|
54
84
|
# The RaTeX XCFramework bundles its own module.modulemap and headers; never let the
|
|
@@ -62,18 +92,9 @@ Pod::Spec.new do |s|
|
|
|
62
92
|
preprocessor_defs = "$(inherited) MD4C_USE_UTF8=1#{code_highlight[:defines]}"
|
|
63
93
|
if enable_math
|
|
64
94
|
preprocessor_defs += ' ENRICHED_MARKDOWN_MATH=1'
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
# by `yarn prepare` in the monorepo), so fail early with an actionable message instead of
|
|
69
|
-
# a confusing missing-file error.
|
|
70
|
-
unless ratex_present
|
|
71
|
-
raise '[ReactNativeEnrichedMarkdown] LaTeX math is enabled but the vendored RaTeX ' \
|
|
72
|
-
'XCFramework is missing at ios/vendor/RaTeX.xcframework. ' \
|
|
73
|
-
'For published installs, re-run: node node_modules/react-native-enriched-markdown/postinstall.mjs ' \
|
|
74
|
-
'For monorepo development, run `yarn prepare` (or `node vendor/vendor-ratex.mjs`). ' \
|
|
75
|
-
"To disable math, set ENV['ENRICHED_MARKDOWN_ENABLE_MATH'] = '0' in your Podfile. See docs/LATEX_MATH.md."
|
|
76
|
-
end
|
|
95
|
+
# enable_math already implies ratex_present (the reconciliation above raises on an
|
|
96
|
+
# explicit opt-in with a missing framework and disables the default-on path), so the
|
|
97
|
+
# vendored references below always resolve.
|
|
77
98
|
# Prebuilt static XCFramework (device + simulator[arm64,x86_64] + macOS). Vendored
|
|
78
99
|
# rather than pulled via spm_dependency, which compiled RaTeX's Swift wrapper per
|
|
79
100
|
# requested arch (breaking universal simulator builds, #527) and double-collected
|
package/android/build.gradle
CHANGED
|
@@ -23,7 +23,52 @@ def getExtOrIntegerDefault(name) {
|
|
|
23
23
|
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["EnrichedMarkdown_" + name]).toInteger()
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
// The consumer app's package.json "enriched-markdown" block is the build-time source of
|
|
27
|
+
// truth for feature toggles (mirrors the iOS podspecs and react-native-worklets). It is
|
|
28
|
+
// read from the Gradle build root -- "<app>/package.json", one level above the "<app>/android"
|
|
29
|
+
// dir -- so in a monorepo it resolves to the app being built, not the workspace root.
|
|
30
|
+
// Per-app config therefore works; the download side (postinstall) is a separate,
|
|
31
|
+
// install-time decision. Gradle properties remain a deprecated fallback.
|
|
32
|
+
def consumerConfig = [:]
|
|
33
|
+
def consumerAppName = null
|
|
34
|
+
def consumerPackageJson = new File(rootProject.projectDir, "../package.json")
|
|
35
|
+
if (consumerPackageJson.exists()) {
|
|
36
|
+
def parsed = new groovy.json.JsonSlurper().parse(consumerPackageJson)
|
|
37
|
+
if (parsed instanceof Map) {
|
|
38
|
+
if (parsed["enriched-markdown"] instanceof Map) {
|
|
39
|
+
consumerConfig = parsed["enriched-markdown"]
|
|
40
|
+
}
|
|
41
|
+
consumerAppName = parsed["name"]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Filesystem-safe per-app slug: package.json "name", else the app directory name -- the
|
|
46
|
+
// same source and fallback the iOS podspec uses (installation root's parent), so both
|
|
47
|
+
// platforms derive an identical slug for the same app. It keys the per-app generated
|
|
48
|
+
// code-highlight registry (generated-<slug>) below so the artifact layout matches iOS and
|
|
49
|
+
// two monorepo apps with different custom language sets never share one dir.
|
|
50
|
+
def consumerAppSlug = (consumerAppName ?: rootProject.projectDir.parentFile?.name ?: "app").toString()
|
|
51
|
+
.replaceAll('[^A-Za-z0-9._-]+', '-').replaceAll('^-+|-+$', '')
|
|
52
|
+
if (!consumerAppSlug) consumerAppSlug = "app"
|
|
53
|
+
|
|
54
|
+
// Math: package.json > gradle property (deprecated) > default true. Android math is a
|
|
55
|
+
// Maven dependency (no downloaded asset), so the flag simply includes or excludes it --
|
|
56
|
+
// there is nothing to be missing, hence no throw as on iOS.
|
|
57
|
+
def mathProp = rootProject.findProperty("enrichedMarkdown.enableMath") ?: findProperty("enrichedMarkdown.enableMath")
|
|
58
|
+
def enableMath
|
|
59
|
+
if (consumerConfig.containsKey("enableMath")) {
|
|
60
|
+
enableMath = consumerConfig.enableMath != false
|
|
61
|
+
if (mathProp != null) {
|
|
62
|
+
logger.warn("[ReactNativeEnrichedMarkdown] DEPRECATED: enrichedMarkdown.enableMath gradle property " +
|
|
63
|
+
"is ignored when \"enriched-markdown\".enableMath is set in your package.json.")
|
|
64
|
+
}
|
|
65
|
+
} else if (mathProp != null) {
|
|
66
|
+
logger.warn("[ReactNativeEnrichedMarkdown] DEPRECATED: enrichedMarkdown.enableMath gradle property " +
|
|
67
|
+
"will be removed in a future version. Configure via \"enriched-markdown\".enableMath in your package.json instead.")
|
|
68
|
+
enableMath = mathProp.toString().toBoolean()
|
|
69
|
+
} else {
|
|
70
|
+
enableMath = true
|
|
71
|
+
}
|
|
27
72
|
|
|
28
73
|
// Default grammar set derived from the single source of truth,
|
|
29
74
|
// vendor/grammar-versions.json (every grammar with default:true), so the compiled
|
|
@@ -39,16 +84,66 @@ if (grammarManifest == null) {
|
|
|
39
84
|
}
|
|
40
85
|
def defaultCodeHighlightLanguages = new groovy.json.JsonSlurper().parse(grammarManifest)
|
|
41
86
|
.grammars.findAll { id, spec -> spec['default'] }.collect { id, spec -> id }
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
// runtime lib.c, fetched first) auto-disables here -- feeding no missing sources to CMake --
|
|
46
|
-
// on a `enriched-markdown`.enableCodeHighlight = false opt-out or a partial/failed download.
|
|
87
|
+
// Code highlight enable: package.json > gradle property (deprecated) > default on.
|
|
88
|
+
// `codeHighlightExplicit` tracks an active opt-in (vs the implicit default), which
|
|
89
|
+
// decides the missing-grammars behavior below.
|
|
47
90
|
def codeHighlightProp = rootProject.findProperty("enrichedMarkdown.enableCodeHighlight") ?: findProperty("enrichedMarkdown.enableCodeHighlight")
|
|
48
91
|
def codeHighlightStamp = new File(projectDir, "../cpp/highlight/vendor/grammars/.stamp")
|
|
49
|
-
def
|
|
92
|
+
def codeHighlightRequested
|
|
93
|
+
def codeHighlightExplicit
|
|
94
|
+
if (consumerConfig.containsKey("enableCodeHighlight")) {
|
|
95
|
+
codeHighlightRequested = consumerConfig.enableCodeHighlight != false
|
|
96
|
+
codeHighlightExplicit = codeHighlightRequested
|
|
97
|
+
if (codeHighlightProp != null) {
|
|
98
|
+
logger.warn("[ReactNativeEnrichedMarkdown] DEPRECATED: enrichedMarkdown.enableCodeHighlight gradle property " +
|
|
99
|
+
"is ignored when \"enriched-markdown\".enableCodeHighlight is set in your package.json.")
|
|
100
|
+
}
|
|
101
|
+
} else if (codeHighlightProp != null) {
|
|
102
|
+
logger.warn("[ReactNativeEnrichedMarkdown] DEPRECATED: enrichedMarkdown.enableCodeHighlight gradle property " +
|
|
103
|
+
"will be removed in a future version. Configure via \"enriched-markdown\".enableCodeHighlight in your package.json instead.")
|
|
104
|
+
codeHighlightRequested = codeHighlightProp.toString().toBoolean()
|
|
105
|
+
codeHighlightExplicit = codeHighlightRequested
|
|
106
|
+
} else {
|
|
107
|
+
codeHighlightRequested = true
|
|
108
|
+
codeHighlightExplicit = false
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// The grammars/.stamp marker is written only after every grammar source is fully vendored
|
|
112
|
+
// at postinstall. An explicit opt-in with the grammars missing fails loud with the fix; on
|
|
113
|
+
// by default but missing (a partial/failed download, or a monorepo root opt-out) falls back
|
|
114
|
+
// to a clean no-op build. Gating on the stamp also keeps CMake from being fed missing sources.
|
|
115
|
+
def enableCodeHighlight
|
|
116
|
+
if (!codeHighlightRequested) {
|
|
117
|
+
enableCodeHighlight = false
|
|
118
|
+
} else if (codeHighlightStamp.exists()) {
|
|
119
|
+
enableCodeHighlight = true
|
|
120
|
+
} else if (codeHighlightExplicit) {
|
|
121
|
+
throw new GradleException("[ReactNativeEnrichedMarkdown] code highlighting is enabled but the tree-sitter " +
|
|
122
|
+
"grammars are not installed. Reinstall to fetch them: `npm rebuild react-native-enriched-markdown`. " +
|
|
123
|
+
"To disable, set \"enriched-markdown\".enableCodeHighlight = false in your app package.json. " +
|
|
124
|
+
"Troubleshooting: https://github.com/software-mansion/enriched-markdown/blob/main/docs/NATIVE_ASSETS.md")
|
|
125
|
+
} else {
|
|
126
|
+
enableCodeHighlight = false
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Languages: package.json > gradle property (deprecated) > manifest defaults. An explicit
|
|
130
|
+
// empty array disables all languages (codeHighlightActive below); only the default/property
|
|
131
|
+
// paths fall back to the manifest set.
|
|
50
132
|
def codeHighlightLanguagesProp = rootProject.findProperty("enrichedMarkdown.codeHighlightLanguages") ?: findProperty("enrichedMarkdown.codeHighlightLanguages")
|
|
51
|
-
def codeHighlightLanguages
|
|
133
|
+
def codeHighlightLanguages
|
|
134
|
+
if (consumerConfig.get("codeHighlightLanguages") instanceof List) {
|
|
135
|
+
codeHighlightLanguages = consumerConfig.codeHighlightLanguages.collect { it.toString().trim() }.findAll { it }
|
|
136
|
+
if (codeHighlightLanguagesProp != null) {
|
|
137
|
+
logger.warn("[ReactNativeEnrichedMarkdown] DEPRECATED: enrichedMarkdown.codeHighlightLanguages gradle property " +
|
|
138
|
+
"is ignored when \"enriched-markdown\".codeHighlightLanguages is set in your package.json.")
|
|
139
|
+
}
|
|
140
|
+
} else if (codeHighlightLanguagesProp) {
|
|
141
|
+
logger.warn("[ReactNativeEnrichedMarkdown] DEPRECATED: enrichedMarkdown.codeHighlightLanguages gradle property " +
|
|
142
|
+
"will be removed in a future version. Configure via \"enriched-markdown\".codeHighlightLanguages in your package.json instead.")
|
|
143
|
+
codeHighlightLanguages = codeHighlightLanguagesProp.toString().split(",").collect { it.trim() }.findAll { it }
|
|
144
|
+
} else {
|
|
145
|
+
codeHighlightLanguages = defaultCodeHighlightLanguages
|
|
146
|
+
}
|
|
52
147
|
def codeHighlightActive = enableCodeHighlight && !codeHighlightLanguages.isEmpty()
|
|
53
148
|
|
|
54
149
|
android {
|
|
@@ -113,8 +208,12 @@ if (codeHighlightActive) {
|
|
|
113
208
|
// Common case: the committed default-set registry ships in-tree, no codegen.
|
|
114
209
|
generatedDir = committedGenerated
|
|
115
210
|
} else {
|
|
116
|
-
// Custom language set: regenerate the registry from the vendored .scm files
|
|
117
|
-
|
|
211
|
+
// Custom language set: regenerate the registry from the vendored .scm files into a
|
|
212
|
+
// per-app dir (generated-<slug>), mirroring iOS. Android rewrites this on every
|
|
213
|
+
// gradle configure so it never had iOS's persistent clash, but keying per app keeps
|
|
214
|
+
// the two platforms' artifact layout identical. (highlight-config.cmake itself stays
|
|
215
|
+
// at the CMakeLists-fixed shared path and is rewritten each configure.)
|
|
216
|
+
generatedDir = new File(highlightConfigDir, "generated-${consumerAppSlug}")
|
|
118
217
|
generatedDir.mkdirs()
|
|
119
218
|
def genScript = [
|
|
120
219
|
new File(projectDir, "../../../vendor/gen-registry.mjs"),
|
|
@@ -138,7 +237,7 @@ if (codeHighlightActive) {
|
|
|
138
237
|
highlightConfigFile.text = """\
|
|
139
238
|
set(ENRICHED_MARKDOWN_CODE_HIGHLIGHT ON)
|
|
140
239
|
set(ENRICHED_MARKDOWN_HIGHLIGHT_LANGUAGES "${codeHighlightLanguages.join(';')}")
|
|
141
|
-
set(ENRICHED_MARKDOWN_HIGHLIGHT_GENERATED_DIR "${generatedDir.canonicalPath}")
|
|
240
|
+
set(ENRICHED_MARKDOWN_HIGHLIGHT_GENERATED_DIR "${generatedDir.canonicalPath.replace('\\', '/')}")
|
|
142
241
|
"""
|
|
143
242
|
} else {
|
|
144
243
|
highlightConfigFile.text = "set(ENRICHED_MARKDOWN_CODE_HIGHLIGHT OFF)\n"
|
|
@@ -9,6 +9,7 @@ import android.os.Looper
|
|
|
9
9
|
import android.text.Layout
|
|
10
10
|
import android.util.AttributeSet
|
|
11
11
|
import android.util.Log
|
|
12
|
+
import android.util.TypedValue
|
|
12
13
|
import android.view.MotionEvent
|
|
13
14
|
import com.facebook.react.bridge.ReadableMap
|
|
14
15
|
import com.facebook.react.uimanager.StateWrapper
|
|
@@ -190,6 +191,10 @@ class EnrichedMarkdownText
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
|
|
194
|
+
fun commitProps() {
|
|
195
|
+
updateMeasurementStoreFontScaling()
|
|
196
|
+
}
|
|
197
|
+
|
|
193
198
|
private fun updateMeasurementStoreFontScaling() {
|
|
194
199
|
MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
|
|
195
200
|
}
|
|
@@ -258,6 +263,10 @@ class EnrichedMarkdownText
|
|
|
258
263
|
private fun applyRenderedText(styledText: CharSequence) {
|
|
259
264
|
val tailStart = previousTextLength
|
|
260
265
|
|
|
266
|
+
markdownStyle?.paragraphStyle?.fontSize?.let {
|
|
267
|
+
setTextSize(TypedValue.COMPLEX_UNIT_PX, it)
|
|
268
|
+
}
|
|
269
|
+
|
|
261
270
|
text = styledText
|
|
262
271
|
|
|
263
272
|
if (movementMethod !is LinkLongPressMovementMethod) {
|
package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt
CHANGED
|
@@ -72,6 +72,11 @@ class EnrichedMarkdownTextManager :
|
|
|
72
72
|
return view
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
override fun onAfterUpdateTransaction(view: EnrichedMarkdownText) {
|
|
76
|
+
super.onAfterUpdateTransaction(view)
|
|
77
|
+
view.commitProps()
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
override fun updateState(
|
|
76
81
|
view: EnrichedMarkdownText,
|
|
77
82
|
props: ReactStylesDiffMap?,
|
|
@@ -19,7 +19,7 @@ import kotlin.math.abs
|
|
|
19
19
|
* Must never mutate the buffer's Selection spans — the platform Editor
|
|
20
20
|
* manages them during long-press gestures, and removing or overwriting
|
|
21
21
|
* them mid-gesture crashes on some OEM skins.
|
|
22
|
-
* See: https://github.com/software-mansion/
|
|
22
|
+
* See: https://github.com/software-mansion/enriched-markdown/issues/580
|
|
23
23
|
*/
|
|
24
24
|
class LinkLongPressMovementMethod : ArrowKeyMovementMethod() {
|
|
25
25
|
private val handler = Handler(Looper.getMainLooper())
|
package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h
CHANGED
|
@@ -12,6 +12,8 @@ inline folly::dynamic toDynamic(const EnrichedMarkdownTextProps &props) {
|
|
|
12
12
|
serializedProps["markdown"] = props.markdown;
|
|
13
13
|
serializedProps["markdownStyle"] = toDynamic(props.markdownStyle);
|
|
14
14
|
serializedProps["md4cFlags"] = toDynamic(props.md4cFlags);
|
|
15
|
+
serializedProps["allowFontScaling"] = props.allowFontScaling;
|
|
16
|
+
serializedProps["maxFontSizeMultiplier"] = props.maxFontSizeMultiplier;
|
|
15
17
|
serializedProps["allowTrailingMargin"] = props.allowTrailingMargin;
|
|
16
18
|
serializedProps["streamingAnimation"] = props.streamingAnimation;
|
|
17
19
|
|
|
@@ -29,6 +31,8 @@ inline folly::dynamic toDynamic(const EnrichedMarkdownProps &props) {
|
|
|
29
31
|
serializedProps["markdown"] = props.markdown;
|
|
30
32
|
serializedProps["markdownStyle"] = toDynamic(props.markdownStyle);
|
|
31
33
|
serializedProps["md4cFlags"] = toDynamic(props.md4cFlags);
|
|
34
|
+
serializedProps["allowFontScaling"] = props.allowFontScaling;
|
|
35
|
+
serializedProps["maxFontSizeMultiplier"] = props.maxFontSizeMultiplier;
|
|
32
36
|
serializedProps["allowTrailingMargin"] = props.allowTrailingMargin;
|
|
33
37
|
serializedProps["streamingAnimation"] = props.streamingAnimation;
|
|
34
38
|
|