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 CHANGED
@@ -1,4 +1,8 @@
1
- <img src="https://github.com/user-attachments/assets/83cb462c-17df-4809-8b8a-fa4abb258cb3" alt="react-native-enriched-markdown by Software Mansion" width="100%">
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. If you don't use a feature, skip
130
- > its download with an `"enriched-markdown": { "enableCodeHighlight": false, "enableMath": false }`
131
- > block in your app's `package.json` — see [Skipping the download](docs/NATIVE_ASSETS.md#skipping-the-download-opt-out).
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](./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/react-native-enriched-markdown.git", :tag => "#{s.version}" }
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
- # Resolution: ENV['ENRICHED_MARKDOWN_ENABLE_MATH'] forces the choice ('0' off, '1' on).
40
- # Otherwise math tracks whether the consumer actually downloaded the framework, so a
41
- # package.json opt-out (`enriched-markdown`.enableMath = false skips the postinstall
42
- # download) yields a clean build with no Podfile edit. To disable explicitly, set
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
- enable_math = math_flag == '1' || (math_flag != '0' && ratex_present)
47
- if !enable_math && math_flag != '0' && !ratex_present
48
- Pod::UI.warn '[ReactNativeEnrichedMarkdown] LaTeX math disabled: the vendored RaTeX ' \
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
- # Reachable only when math is force-enabled (ENRICHED_MARKDOWN_ENABLE_MATH='1') but the
66
- # vendored tree is missing; the unforced path already auto-disables above. ios/vendor is
67
- # kept out of the npm tarball and restored on the consumer's machine by postinstall (or
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
@@ -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
- def enableMath = (rootProject.findProperty("enrichedMarkdown.enableMath") ?: findProperty("enrichedMarkdown.enableMath") ?: "true").toString().toBoolean()
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
- // The enrichedMarkdown.enableCodeHighlight gradle property forces the choice. Otherwise
43
- // code highlighting tracks the vendored grammars/.stamp marker, which postinstall writes
44
- // only after every grammar source is fully vendored. Gating on the stamp (rather than the
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 enableCodeHighlight = codeHighlightProp != null ? codeHighlightProp.toString().toBoolean() : codeHighlightStamp.exists()
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 = codeHighlightLanguagesProp ? codeHighlightLanguagesProp.toString().split(",").collect { it.trim() }.findAll { it } : defaultCodeHighlightLanguages
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
- generatedDir = new File(highlightConfigDir, "generated")
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) {
@@ -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/react-native-enriched-markdown/issues/580
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())
@@ -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