@actualwave/react-native-codeditor 1.1.0 → 1.2.0
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/CHANGELOG.md +28 -0
- package/README.md +16 -6
- package/SKILL.md +469 -0
- package/THIRD_PARTY_NOTICES +120 -0
- package/app.plugin.js +1 -1
- package/lib/module/CodeEditor.js +69 -2
- package/lib/typescript/src/CodeEditor.d.ts +20 -2
- package/lib/typescript/src/EditorAPI.d.ts +42 -1
- package/lib/typescript/src/WebViewAPI.d.ts +4 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/package.json +12 -4
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-core.js +39 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-css.js +19 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-glsl.js +1 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-graphql.js +50 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-icu-messageformat.js +1 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-react-native.js +6 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-sksl.js +7 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-sql.js +5 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-embed-tailwind.js +63 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-glsl.js +20 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-icu-messageformat.js +11 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-react-native.js +71 -0
- package/src/assets/codemirror/@actualwave_codemirror-lang-sksl.js +7 -2
- package/src/assets/codemirror/@codemirror_autocomplete.js +9 -9
- package/src/assets/codemirror/@codemirror_commands.js +86 -86
- package/src/assets/codemirror/@codemirror_lang-css.js +2 -2
- package/src/assets/codemirror/@codemirror_lang-go.js +1 -1
- package/src/assets/codemirror/@codemirror_lang-html.js +1 -1
- package/src/assets/codemirror/@codemirror_lang-javascript.js +4 -4
- package/src/assets/codemirror/@codemirror_lang-jinja.js +1 -1
- package/src/assets/codemirror/@codemirror_lang-json.js +1 -1
- package/src/assets/codemirror/@codemirror_lang-less.js +1 -1
- package/src/assets/codemirror/@codemirror_lang-liquid.js +1 -1
- package/src/assets/codemirror/@codemirror_lang-markdown.js +2 -2
- package/src/assets/codemirror/@codemirror_lang-python.js +1 -1
- package/src/assets/codemirror/@codemirror_lang-sql.js +4 -4
- package/src/assets/codemirror/@codemirror_lang-xml.js +1 -1
- package/src/assets/codemirror/@codemirror_language.js +11 -11
- package/src/assets/codemirror/@codemirror_legacy-modes_mode_clike.js +1 -1
- package/src/assets/codemirror/@codemirror_legacy-modes_mode_mathematica.js +1 -1
- package/src/assets/codemirror/@codemirror_legacy-modes_mode_oz.js +1 -1
- package/src/assets/codemirror/@codemirror_legacy-modes_mode_verilog.js +1 -1
- package/src/assets/codemirror/@codemirror_lint.js +5 -5
- package/src/assets/codemirror/@codemirror_merge.js +4 -4
- package/src/assets/codemirror/@codemirror_search.js +8 -8
- package/src/assets/codemirror/@codemirror_state.js +1 -1
- package/src/assets/codemirror/@codemirror_theme-one-dark.js +3 -3
- package/src/assets/codemirror/@codemirror_view.js +6 -6
- package/src/assets/codemirror/@lezer_common.js +2 -2
- package/src/assets/codemirror/@lezer_css.js +1 -1
- package/src/assets/codemirror/@lezer_javascript.js +1 -1
- package/src/assets/codemirror/@lezer_lr.js +1 -1
- package/src/assets/codemirror/@lezer_markdown.js +4 -4
- package/src/assets/codemirror/@lezer_sass.js +1 -1
- package/src/assets/codemirror/_core.js +129 -129
- package/src/assets/codemirror-editor.umd.js +130 -17
- package/src/assets/editor.html +25 -1
- package/lib/typescript/app.plugin.d.ts +0 -3
- package/lib/typescript/babel.config.d.ts +0 -10
- package/lib/typescript/react-native.config.d.ts +0 -2
- package/lib/typescript/scripts/copy-assets.d.ts +0 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `languages` prop on `<CodeEditor>` and `api.editor.registerLanguage(name, packageName)` for
|
|
7
|
+
language packages that don't follow the `@codemirror/lang-{name}` naming convention
|
|
8
|
+
(e.g. `{ sksl: '@actualwave/codemirror-lang-sksl' }`). The prop registers before the initial
|
|
9
|
+
`language` is resolved.
|
|
10
|
+
- `languageConfig` prop and `setLanguage(name, config?, embeds?)` — options passed to the
|
|
11
|
+
language factory (e.g. `{ jsx: true, typescript: true }`).
|
|
12
|
+
- `embeds` prop, `api.editor.registerTaggedTemplate()` and `api.editor.registerSupportExtension()`
|
|
13
|
+
for tagged-template DSL embeddings and support extensions in `javascript`.
|
|
14
|
+
- `CompletionItem` and `EmbedsConfig` types are now exported.
|
|
15
|
+
- `THIRD_PARTY_NOTICES`, `SKILL.md` and `CHANGELOG.md` are included in the package.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Updated bundled `@actualwave/codemirror-package` assets to 0.1.4.
|
|
19
|
+
- `sksl` (and other `@actualwave/codemirror-lang-*` packages) are no longer pre-registered by the
|
|
20
|
+
bundled codemirror-package (it was an undocumented built-in in 1.1.0). Pass
|
|
21
|
+
`languages={{ sksl: '@actualwave/codemirror-lang-sksl' }}` or call `api.editor.registerLanguage()`
|
|
22
|
+
before using them; otherwise `setLanguage` rejects with "No language support found".
|
|
23
|
+
- `lib/typescript` no longer contains declaration files for repo config files.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Documentation and example for the iOS `editorUri` used `FileSystem.bundleDirectory`, which is not
|
|
27
|
+
available from the default `expo-file-system` entry point in Expo SDK 55. Use
|
|
28
|
+
`new File(Paths.bundle, 'assets/codeditor/editor.html').uri`.
|
package/README.md
CHANGED
|
@@ -144,16 +144,16 @@ npm install expo-file-system
|
|
|
144
144
|
|
|
145
145
|
```tsx
|
|
146
146
|
import { Platform } from 'react-native';
|
|
147
|
-
import
|
|
147
|
+
import { File, Paths } from 'expo-file-system';
|
|
148
148
|
|
|
149
149
|
const IOS_EDITOR_URI = Platform.OS === 'ios'
|
|
150
|
-
? (
|
|
150
|
+
? new File(Paths.bundle, 'assets/codeditor/editor.html').uri
|
|
151
151
|
: undefined;
|
|
152
152
|
|
|
153
153
|
<CodeEditor editorUri={IOS_EDITOR_URI} ... />
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
`
|
|
156
|
+
`Paths.bundle` is the `.app` folder in the bundle (e.g.
|
|
157
157
|
`file:///var/containers/Bundle/Application/<UUID>/MyApp.app/`), which is stable on both
|
|
158
158
|
simulators and real devices regardless of where iOS installed the app.
|
|
159
159
|
|
|
@@ -224,6 +224,7 @@ export default function EditorScreen() {
|
|
|
224
224
|
|---|---|---|---|
|
|
225
225
|
| `content` | `string` | `''` | Initial document content (see [Content model](#content-model) below). |
|
|
226
226
|
| `language` | `string` | `undefined` | Syntax language, e.g. `'javascript'`, `'python'`, `'sql'`. The language module is loaded from the bundled assets on first use. |
|
|
227
|
+
| `languages` | `Record<string, string>` | `undefined` | Custom language packages as `{ name: packageName }`, for languages that don't follow the `@codemirror/lang-{name}` convention, e.g. `{ sksl: '@actualwave/codemirror-lang-sksl' }`. Registered before the initial `language` is resolved. The package must be bundled in the WebView assets. |
|
|
227
228
|
| `extensions` | `ExtensionSpec[]` | `[]` | Additional CodeMirror 6 extension specs. See [Extension specs](#extension-specs). |
|
|
228
229
|
| `theme` | `string` | `undefined` | Theme name. See [Themes](#themes). |
|
|
229
230
|
| `viewport` | `ViewportSettings` | `undefined` | Controls the `<meta name="viewport">` tag inside the WebView. |
|
|
@@ -314,6 +315,12 @@ api.editor.setLanguage(name: string): Promise<void>
|
|
|
314
315
|
// Switches syntax language. Loads the language module on demand.
|
|
315
316
|
// e.g. await api.editor.setLanguage('python')
|
|
316
317
|
|
|
318
|
+
api.editor.registerLanguage(name: string, packageName: string): Promise<void>
|
|
319
|
+
// Maps a language name to a package that doesn't follow @codemirror/lang-{name}.
|
|
320
|
+
// Takes effect on the next setLanguage(). Alternative to the `languages` prop.
|
|
321
|
+
// e.g. await api.editor.registerLanguage('sksl', '@actualwave/codemirror-lang-sksl');
|
|
322
|
+
// await api.editor.setLanguage('sksl')
|
|
323
|
+
|
|
317
324
|
api.editor.setExtensions(specs: ExtensionSpec[]): Promise<void>
|
|
318
325
|
// Replaces the active extension set.
|
|
319
326
|
// e.g. await api.editor.setExtensions(['@codemirror/search'])
|
|
@@ -451,9 +458,9 @@ api.editor.unregisterShortcut(key: string): Promise<void>
|
|
|
451
458
|
|
|
452
459
|
```tsx
|
|
453
460
|
<CodeEditor
|
|
454
|
-
onInitialized={(api) => {
|
|
455
|
-
|
|
456
|
-
|
|
461
|
+
onInitialized={async (api) => {
|
|
462
|
+
await api.editor.registerShortcut('Mod-s', 'save');
|
|
463
|
+
await api.editor.registerShortcut('Mod-Enter', 'run');
|
|
457
464
|
}}
|
|
458
465
|
onShortcut={(name) => {
|
|
459
466
|
if (name === 'save') handleSave();
|
|
@@ -567,6 +574,9 @@ Pass any of these to the `language` prop or `api.editor.setLanguage()`:
|
|
|
567
574
|
`less` `lezer` `liquid` `markdown` `php` `python` `rust` `sass` `sql`
|
|
568
575
|
`vue` `wast` `xml` `yaml`
|
|
569
576
|
|
|
577
|
+
Other bundled packages such as `sksl` are not auto-detected — register them with the
|
|
578
|
+
`languages` prop or `api.editor.registerLanguage()`.
|
|
579
|
+
|
|
570
580
|
Legacy modes (100+ additional languages via `@codemirror/legacy-modes`) can be loaded
|
|
571
581
|
manually with `api.editor.loadExtension()`:
|
|
572
582
|
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-native-codeditor
|
|
3
|
+
description: >
|
|
4
|
+
Embed and control a CodeMirror 6 code editor inside a React Native WebView using
|
|
5
|
+
@actualwave/react-native-codeditor. Use when adding a code editor to a React Native
|
|
6
|
+
app, controlling editor content/language/theme/cursor/selection/history programmatically,
|
|
7
|
+
registering custom keyboard shortcuts, handling editor events (content changes, history
|
|
8
|
+
size, selection), or setting up native asset copying for Android/iOS.
|
|
9
|
+
license: MIT
|
|
10
|
+
compatibility: React Native ≥ 0.71, react-native-webview ≥ 11, Android WebView 61+, iOS with WKWebView. expo-file-system required for iOS URI resolution.
|
|
11
|
+
metadata:
|
|
12
|
+
package: "@actualwave/react-native-codeditor"
|
|
13
|
+
npm: "https://www.npmjs.com/package/@actualwave/react-native-codeditor"
|
|
14
|
+
repository: "https://github.com/burdiuz/react-native-codeditor"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# @actualwave/react-native-codeditor — Agent Skill
|
|
18
|
+
|
|
19
|
+
CodeMirror 6 code editor for React Native, embedded in a WebView with a full bidirectional RPC bridge. Fully offline — all CodeMirror assets are bundled. Works on Android and iOS.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Exports
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import CodeEditor from '@actualwave/react-native-codeditor';
|
|
27
|
+
// or named (WebViewAPI is the class itself, exported as a value):
|
|
28
|
+
import { CodeEditor, WebViewAPI } from '@actualwave/react-native-codeditor';
|
|
29
|
+
|
|
30
|
+
// Types
|
|
31
|
+
import type {
|
|
32
|
+
CodeEditorProps, // all props for <CodeEditor />
|
|
33
|
+
WebViewAPIHandlers, // handler callbacks
|
|
34
|
+
WebViewRef, // { injectJavaScript, requestFocus? }
|
|
35
|
+
InitialConfig, // { content?, language?, languageConfig?, embeds?, languages?, extensions?, theme?, viewport? }
|
|
36
|
+
EditorAPI, // full interface of api.editor proxy methods
|
|
37
|
+
ExtensionSpec, // string | [string, string] | [string, object] | unknown
|
|
38
|
+
ViewportSettings, // { intialScale?, maximumScale?, minimumScale?, userScalable?, viewportWidth? }
|
|
39
|
+
CursorPosition, // { line: number, ch: number, index: number }
|
|
40
|
+
HistorySize, // { undo: number, redo: number }
|
|
41
|
+
CompletionItem, // { label, type?, detail?, info? }
|
|
42
|
+
EmbedsConfig, // { taggedTemplates?, supportExtensions? }
|
|
43
|
+
} from '@actualwave/react-native-codeditor';
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install @actualwave/react-native-codeditor react-native-webview
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Copy assets to Android** (required — WebView loads these files at runtime):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
mkdir -p android/app/src/main/assets/codeditor
|
|
58
|
+
cp -r node_modules/@actualwave/react-native-codeditor/src/assets/* android/app/src/main/assets/codeditor/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Expo (recommended)** — add plugin to `app.json`, then `expo prebuild`:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{ "expo": { "plugins": ["@actualwave/react-native-codeditor"] } }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**iOS** — requires `expo-file-system` for the runtime bundle path:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm install expo-file-system
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { File, Paths } from 'expo-file-system';
|
|
75
|
+
const IOS_EDITOR_URI = Platform.OS === 'ios'
|
|
76
|
+
? new File(Paths.bundle, 'assets/codeditor/editor.html').uri
|
|
77
|
+
: undefined;
|
|
78
|
+
<CodeEditor editorUri={IOS_EDITOR_URI} ... />
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Android manifest** — add `adjustResize` so the editor shrinks when the keyboard appears:
|
|
82
|
+
|
|
83
|
+
```xml
|
|
84
|
+
<activity android:windowSoftInputMode="adjustResize" ... />
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**After upgrading** — always re-copy assets:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
cp -r node_modules/@actualwave/react-native-codeditor/src/assets/* android/app/src/main/assets/codeditor/
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Basic usage
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { useCallback, useRef } from 'react';
|
|
99
|
+
import { KeyboardAvoidingView, Platform } from 'react-native';
|
|
100
|
+
import CodeEditor from '@actualwave/react-native-codeditor';
|
|
101
|
+
import type { WebViewAPI, HistorySize } from '@actualwave/react-native-codeditor';
|
|
102
|
+
|
|
103
|
+
export default function EditorScreen() {
|
|
104
|
+
const apiRef = useRef<WebViewAPI | null>(null);
|
|
105
|
+
|
|
106
|
+
const handleInitialized = useCallback((api: WebViewAPI) => {
|
|
107
|
+
apiRef.current = api;
|
|
108
|
+
void api.focus(); // opens Android soft keyboard
|
|
109
|
+
}, []);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<KeyboardAvoidingView style={{ flex: 1 }} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
|
113
|
+
<CodeEditor
|
|
114
|
+
content="const x = 42;"
|
|
115
|
+
language="javascript"
|
|
116
|
+
theme="darcula"
|
|
117
|
+
onInitialized={handleInitialized}
|
|
118
|
+
onContentUpdate={(content) => console.log(content.length)}
|
|
119
|
+
onHistorySizeUpdate={(size) => console.log(size.undo, size.redo)}
|
|
120
|
+
onLog={(...args) => console.log('[editor]', ...args)}
|
|
121
|
+
onError={(err) => console.error('[editor]', err)}
|
|
122
|
+
/>
|
|
123
|
+
</KeyboardAvoidingView>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Architecture
|
|
131
|
+
|
|
132
|
+
Two runtimes connected via DDA (Deferred Data Access) RPC over the WebView bridge:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
React Native (HOST) WebView (GUEST)
|
|
136
|
+
────────────────── ───────────────
|
|
137
|
+
CodeEditor component
|
|
138
|
+
└─ WebViewAPI
|
|
139
|
+
└─ initializeHost() ◄──► initializeGuest()
|
|
140
|
+
api.editor.* ──────► EditorController methods
|
|
141
|
+
(DDA proxy) ◄────── Promise results
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Out-of-band messages** (bypass DDA, sent via `ReactNativeWebView.postMessage`):
|
|
145
|
+
|
|
146
|
+
| Type | Direction | Meaning |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `__editorReady__` | WebView→RN | Editor fully painted; `onInitialized` fires |
|
|
149
|
+
| `__contentChange__` | WebView→RN | Edit, debounced 300ms — carries `{ value, undo, redo }` |
|
|
150
|
+
| `__selectionChange__` | WebView→RN | Selection changed — carries selected text |
|
|
151
|
+
| `__shortcut__` | WebView→RN | Registered shortcut triggered — carries name string |
|
|
152
|
+
| `__editorLog__` | WebView→RN | `window.log(...)` from WebView |
|
|
153
|
+
| `__editorError__` | WebView→RN | `window.onerror` from WebView |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## DDA lazy mode — critical rule
|
|
158
|
+
|
|
159
|
+
DDA operates in **lazy mode**: a proxy call builds a command chain but does NOT send it until the returned value is awaited. **Every `api.editor.*` call MUST be awaited.**
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// ✅ correct
|
|
163
|
+
await apiRef.current?.editor?.historyUndo();
|
|
164
|
+
|
|
165
|
+
// ✅ correct — async IIFE in useEffect
|
|
166
|
+
void (async () => { await apiRef.current!.editor.setLanguage('python'); })();
|
|
167
|
+
|
|
168
|
+
// ❌ wrong — command is never sent
|
|
169
|
+
void apiRef.current?.editor.historyUndo();
|
|
170
|
+
apiRef.current?.editor.historyUndo();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Props
|
|
176
|
+
|
|
177
|
+
### Required callbacks
|
|
178
|
+
|
|
179
|
+
| Prop | Type | Description |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| `onInitialized` | `(api: WebViewAPI) => void` | Fires when editor is fully ready. Store `api` here. Call `api.focus()` for Android keyboard. |
|
|
182
|
+
| `onContentUpdate` | `(content: string) => void` | After edits (debounced 300ms), full document text. |
|
|
183
|
+
| `onHistorySizeUpdate` | `(size: HistorySize) => void` | After edits (debounced 300ms), `{ undo, redo }` depths. |
|
|
184
|
+
| `onLog` | `(...args: unknown[]) => void` | `window.log()` from the WebView. |
|
|
185
|
+
| `onError` | `(error: unknown) => void` | `window.onerror` from the WebView. |
|
|
186
|
+
|
|
187
|
+
### Optional callbacks
|
|
188
|
+
|
|
189
|
+
| Prop | Type | Description |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| `onSelectionChange` | `(text: string) => void` | Called when selection changes; receives selected text (empty string when collapsed). |
|
|
192
|
+
| `onShortcut` | `(name: string) => void` | Called when a shortcut registered via `api.editor.registerShortcut()` is triggered. Receives the name string passed at registration time. |
|
|
193
|
+
|
|
194
|
+
### Editor configuration
|
|
195
|
+
|
|
196
|
+
| Prop | Type | Default | Description |
|
|
197
|
+
|---|---|---|---|
|
|
198
|
+
| `content` | `string` | `''` | Document content. Initial value is delivered at startup; later prop changes call `setValue` if they differ from the editor's current text. |
|
|
199
|
+
| `language` | `string` | — | Syntax language, e.g. `'javascript'`, `'python'`. Loaded on demand. |
|
|
200
|
+
| `languageConfig` | `Record<string, unknown>` | — | Options passed to the language factory, e.g. `{ jsx: true, typescript: true }` for `'javascript'`. |
|
|
201
|
+
| `languages` | `Record<string, string>` | — | Custom language packages `{ name: packageName }` for names that don't follow `@codemirror/lang-{name}`, e.g. `{ sksl: '@actualwave/codemirror-lang-sksl' }`. Registered before the initial `language` is resolved. |
|
|
202
|
+
| `embeds` | `EmbedsConfig` | — | Tagged-template DSL embeddings and support extensions mixed into `'javascript'`: `{ taggedTemplates?: string[], supportExtensions?: (string \| [string, object])[] }`. |
|
|
203
|
+
| `extensions` | `ExtensionSpec[]` | `[]` | CM6 extension specs. |
|
|
204
|
+
| `theme` | `string` | — | Theme name, e.g. `'darcula'`, `'monokai'`. |
|
|
205
|
+
| `viewport` | `ViewportSettings` | — | `<meta name="viewport">` options. |
|
|
206
|
+
|
|
207
|
+
### WebView / layout
|
|
208
|
+
|
|
209
|
+
| Prop | Type | Default | Description |
|
|
210
|
+
|---|---|---|---|
|
|
211
|
+
| `editorUri` | `string` | `'file:///android_asset/codeditor/editor.html'` | Override for iOS — use `new File(Paths.bundle, 'assets/codeditor/editor.html').uri` from `expo-file-system`. |
|
|
212
|
+
| `allowFileAccess` | `boolean` | `true` | Required for `file://` asset loading. |
|
|
213
|
+
| `renderBlockingView` | `() => ReactNode` | `() => <BlockingView />` | Loading overlay while editor initialises. |
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## `WebViewAPI` — editor control
|
|
218
|
+
|
|
219
|
+
`api` is received in `onInitialized`. `api.editor` is a DDA proxy — all its methods return Promises.
|
|
220
|
+
|
|
221
|
+
### Focus
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
api.focus(): Promise<void>
|
|
225
|
+
// Also calls webView.requestFocus() for Android keyboard.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Content
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
api.editor.getValue(): Promise<string>
|
|
232
|
+
api.editor.setValue(value: string): Promise<void> // preserves history
|
|
233
|
+
api.editor.resetValue(value?: string): Promise<void> // clears history
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Language / theme / extensions
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
api.editor.setLanguage(name: string, config?: Record<string, unknown>, embeds?: EmbedsConfig): Promise<void>
|
|
240
|
+
api.editor.registerLanguage(name: string, packageName: string): Promise<void>
|
|
241
|
+
// Maps a name to a package not following @codemirror/lang-{name}; applies on the next setLanguage().
|
|
242
|
+
// e.g. await registerLanguage('sksl', '@actualwave/codemirror-lang-sksl'); await setLanguage('sksl');
|
|
243
|
+
api.editor.registerTaggedTemplate(packageName: string): Promise<void>
|
|
244
|
+
api.editor.registerSupportExtension(packageName: string, config?: Record<string, unknown>): Promise<void>
|
|
245
|
+
// Both register globally for the page's lifetime ('javascript' only); re-call setLanguage('javascript') to apply.
|
|
246
|
+
api.editor.setTheme(themeName?: string): Promise<void> // undefined removes theme
|
|
247
|
+
api.editor.setExtensions(specs: ExtensionSpec[]): Promise<void>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Cursor and selection
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
api.editor.getCursor(where?: 'from' | 'to' | 'head'): Promise<CursorPosition>
|
|
254
|
+
// CursorPosition = { line: number, ch: number, index: number } (line is 0-based)
|
|
255
|
+
api.editor.setCursor(line: number, ch?: number): Promise<void>
|
|
256
|
+
api.editor.getSelection(): Promise<string>
|
|
257
|
+
api.editor.setSelection(anchor: number, head?: number): Promise<void>
|
|
258
|
+
api.editor.replaceSelection(text: string): Promise<void>
|
|
259
|
+
api.editor.cancelSelection(): Promise<void>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### History
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
api.editor.historyUndo(): Promise<boolean>
|
|
266
|
+
api.editor.historyRedo(): Promise<boolean>
|
|
267
|
+
api.editor.historyClear(): Promise<void>
|
|
268
|
+
api.editor.historySize(): Promise<HistorySize> // { undo, redo }
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Editing commands
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
api.editor.indentMore(): Promise<boolean>
|
|
275
|
+
api.editor.indentLess(): Promise<boolean>
|
|
276
|
+
api.editor.toggleComment(): Promise<boolean>
|
|
277
|
+
api.editor.moveLineUp(): Promise<boolean>
|
|
278
|
+
api.editor.moveLineDown(): Promise<boolean>
|
|
279
|
+
api.editor.deleteLine(): Promise<boolean>
|
|
280
|
+
api.editor.selectLine(): Promise<boolean>
|
|
281
|
+
api.editor.selectParentSyntax(): Promise<boolean>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Autocomplete
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
api.editor.startCompletion(): Promise<void>
|
|
288
|
+
api.editor.setCompletions(items: CompletionItem[]): Promise<void>
|
|
289
|
+
// CompletionItem = { label, type?, detail?, info? }
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Custom shortcuts (hardware keyboard)
|
|
293
|
+
|
|
294
|
+
Register key bindings from the React Native side. When triggered in the editor, fires `onShortcut` on the `<CodeEditor>` component with the given name. Shortcuts use `Prec.highest` priority, overriding all built-in keymaps.
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
api.editor.registerShortcut(key: string, name: string): Promise<void>
|
|
298
|
+
api.editor.unregisterShortcut(key: string): Promise<void>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Key notation: `Mod` = Cmd on macOS/iOS, Ctrl on Android/Windows. Examples: `'Mod-s'`, `'Mod-Enter'`, `'Mod-Shift-f'`, `'F5'`.
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
// Register in onInitialized, handle in onShortcut
|
|
305
|
+
<CodeEditor
|
|
306
|
+
onInitialized={async (api) => {
|
|
307
|
+
await api.editor.registerShortcut('Mod-s', 'save');
|
|
308
|
+
await api.editor.registerShortcut('Mod-Enter', 'run');
|
|
309
|
+
}}
|
|
310
|
+
onShortcut={(name) => {
|
|
311
|
+
if (name === 'save') handleSave();
|
|
312
|
+
if (name === 'run') handleRun();
|
|
313
|
+
}}
|
|
314
|
+
...
|
|
315
|
+
/>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Font / keyboard / scroll / advanced
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
api.editor.setFontSize(size: number): Promise<void>
|
|
322
|
+
api.editor.setSoftKeyboard(enabled: boolean): Promise<void>
|
|
323
|
+
api.editor.setViewport(options: ViewportSettings): Promise<void>
|
|
324
|
+
api.editor.scrollToCursor(margin?: number): Promise<void>
|
|
325
|
+
api.editor.loadExtension(moduleName: string): Promise<object>
|
|
326
|
+
api.editor.destroy(): Promise<void>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Synchronous RN-side only
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
api.injectJavaScript(code: string): void
|
|
333
|
+
api.requestFocus(): void
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Content model
|
|
339
|
+
|
|
340
|
+
`content` sets the initial document, and later prop changes are pushed to the editor via `setValue` — but only when they differ from the text the editor last reported, so writing `onContentUpdate` output back to `content` is a harmless no-op. Because `onContentUpdate` is debounced (300ms), avoid transforming the text and feeding it back while the user is typing.
|
|
341
|
+
|
|
342
|
+
To push content programmatically you can also use the API:
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
await api.editor.setValue(newCode); // preserve history
|
|
346
|
+
await api.editor.resetValue(newCode); // clear history (e.g. opening new file)
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Extension specs
|
|
352
|
+
|
|
353
|
+
`ExtensionSpec` accepted by `extensions` prop and `api.editor.setExtensions()`:
|
|
354
|
+
|
|
355
|
+
| Form | Example | Behaviour |
|
|
356
|
+
|---|---|---|
|
|
357
|
+
| Package name string | `'@codemirror/search'` | Loaded via built-in registry |
|
|
358
|
+
| `[packageName, exportName]` | `['@uiw/codemirror-theme-nord', 'nord']` | Returns `mod[exportName]` |
|
|
359
|
+
| `[packageName, options]` | `['@codemirror/search', { top: true }]` | Resolver called with options |
|
|
360
|
+
| Pre-built extension | `myExtension` | Used as-is |
|
|
361
|
+
|
|
362
|
+
Built-in registry: `@codemirror/autocomplete`, `@codemirror/search`, `@codemirror/lint`, `@codemirror/collab`, `@codemirror/theme-one-dark`.
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## Supported languages
|
|
367
|
+
|
|
368
|
+
`angular` `cpp` `css` `go` `html` `java` `javascript` `jinja` `json` `less` `lezer`
|
|
369
|
+
`liquid` `markdown` `php` `python` `rust` `sass` `sql` `vue` `wast` `xml` `yaml`
|
|
370
|
+
|
|
371
|
+
Bundled packages that don't follow the `@codemirror/lang-{name}` naming (e.g. `sksl` →
|
|
372
|
+
`@actualwave/codemirror-lang-sksl`) are not auto-detected — map them with the `languages`
|
|
373
|
+
prop or `api.editor.registerLanguage()` first, otherwise `setLanguage` rejects with
|
|
374
|
+
"No language support found".
|
|
375
|
+
|
|
376
|
+
Legacy modes (100+ more) via `loadExtension`:
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
const { swift } = await api.editor.loadExtension('@codemirror/legacy-modes/mode/swift');
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Themes
|
|
385
|
+
|
|
386
|
+
`androidstudio` `andromeda` `atomone` `aura` `basic` `bbedit` `copilot` `darcula`
|
|
387
|
+
`dracula` `duotone` `eclipse` `github` `material` `monokai` `nord` `okaidia` `solarized`
|
|
388
|
+
`sublime` `tokyoNight` `vscode` `xcode`
|
|
389
|
+
|
|
390
|
+
Two-word themes use camelCase: `tokyoNight`, `githubDark`, `githubLight`, `vscodeDark`, `xcodeDark`, `xcodeLight`, `solarizedDark`, `solarizedLight`.
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Built-in keyboard shortcuts
|
|
395
|
+
|
|
396
|
+
The editor ships with standard CodeMirror 6 keymaps active by default.
|
|
397
|
+
|
|
398
|
+
### Editing (`defaultKeymap`)
|
|
399
|
+
| Key | Action |
|
|
400
|
+
|---|---|
|
|
401
|
+
| `Enter` | Insert newline |
|
|
402
|
+
| `Backspace` / `Delete` | Delete character |
|
|
403
|
+
| `Tab` | Indent |
|
|
404
|
+
| `Shift-Tab` | Unindent |
|
|
405
|
+
| `Mod-a` | Select all |
|
|
406
|
+
|
|
407
|
+
### History (`historyKeymap`)
|
|
408
|
+
| Key | Action |
|
|
409
|
+
|---|---|
|
|
410
|
+
| `Mod-z` | Undo |
|
|
411
|
+
| `Mod-y` / `Mod-Shift-z` | Redo |
|
|
412
|
+
|
|
413
|
+
### Search (`searchKeymap`)
|
|
414
|
+
| Key | Action |
|
|
415
|
+
|---|---|
|
|
416
|
+
| `Mod-f` | Open search panel |
|
|
417
|
+
| `F3` / `Mod-g` | Find next |
|
|
418
|
+
| `Escape` | Close search panel |
|
|
419
|
+
|
|
420
|
+
### Code folding (`foldKeymap`)
|
|
421
|
+
| Key | Action |
|
|
422
|
+
|---|---|
|
|
423
|
+
| `Mod-Shift-[` | Fold at cursor |
|
|
424
|
+
| `Mod-Shift-]` | Unfold at cursor |
|
|
425
|
+
|
|
426
|
+
### Autocomplete (`completionKeymap`)
|
|
427
|
+
| Key | Action |
|
|
428
|
+
|---|---|
|
|
429
|
+
| `Ctrl-Space` | Trigger completion |
|
|
430
|
+
| `Enter` / `Tab` | Accept completion |
|
|
431
|
+
| `Escape` | Close completion |
|
|
432
|
+
|
|
433
|
+
> On mobile, most shortcuts require a hardware keyboard. Use `api.editor.*` commands programmatically instead.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Keyboard / layout
|
|
438
|
+
|
|
439
|
+
Wrap in `KeyboardAvoidingView` so the editor shrinks when the soft keyboard appears:
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
<KeyboardAvoidingView style={{ flex: 1 }} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
|
443
|
+
<CodeEditor ... />
|
|
444
|
+
</KeyboardAvoidingView>
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
Call `api.focus()` inside `onInitialized` to trigger the Android soft keyboard immediately.
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## Common pitfalls
|
|
452
|
+
|
|
453
|
+
**DDA calls not dispatched** — forgetting `await` silently does nothing. Every `api.editor.*` must be awaited.
|
|
454
|
+
|
|
455
|
+
**`onInitialized` timing** — `api` is not available until this fires. Guard all API calls with `if (!apiRef.current) return`.
|
|
456
|
+
|
|
457
|
+
**Content updates are debounced** — `onContentUpdate` fires 300ms after the last edit, so `content` may briefly lag behind the editor. Don't rewrite `content` with modified text mid-typing.
|
|
458
|
+
|
|
459
|
+
**`setLanguage` rejects for unregistered names** — custom packages like `sksl` must be registered via the `languages` prop or `registerLanguage()` first.
|
|
460
|
+
|
|
461
|
+
**Android assets not copied** — if the WebView shows "Error loading page", the `src/assets/` files haven't been copied to `android/app/src/main/assets/codeditor/`. Re-run the copy command.
|
|
462
|
+
|
|
463
|
+
**iOS URI** — the default `editorUri` is Android-only. iOS requires `new File(Paths.bundle, 'assets/codeditor/editor.html').uri` from `expo-file-system` (SDK 54+ API; on older SDKs use `FileSystem.bundleDirectory`).
|
|
464
|
+
|
|
465
|
+
**Upgrading the library** — always re-copy assets after upgrading:
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
cp -r node_modules/@actualwave/react-native-codeditor/src/assets/* android/app/src/main/assets/codeditor/
|
|
469
|
+
```
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
THIRD PARTY NOTICES
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
This package distributes compiled browser assets built from the following
|
|
5
|
+
open-source libraries. Their licenses and copyright notices are reproduced
|
|
6
|
+
below as required by the MIT License.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
-------------------------------------------------------------------------------
|
|
10
|
+
CodeMirror, @codemirror/*, @lezer/*, crelt, style-mod, w3c-keyname,
|
|
11
|
+
@marijn/find-cluster-break
|
|
12
|
+
-------------------------------------------------------------------------------
|
|
13
|
+
MIT License
|
|
14
|
+
|
|
15
|
+
Copyright (C) 2018-2024 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
18
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
19
|
+
in the Software without restriction, including without limitation the rights
|
|
20
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
21
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
22
|
+
furnished to do so, subject to the following conditions:
|
|
23
|
+
|
|
24
|
+
The above copyright notice and this permission notice shall be included in all
|
|
25
|
+
copies or substantial portions of the Software.
|
|
26
|
+
|
|
27
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
28
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
29
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
30
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
31
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
32
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
33
|
+
SOFTWARE.
|
|
34
|
+
|
|
35
|
+
https://codemirror.net/
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
-------------------------------------------------------------------------------
|
|
39
|
+
@uiw/codemirror-themes, @uiw/codemirror-theme-*
|
|
40
|
+
-------------------------------------------------------------------------------
|
|
41
|
+
MIT License
|
|
42
|
+
|
|
43
|
+
Copyright (c) 2022 kenny wong <wowohoo@qq.com>
|
|
44
|
+
|
|
45
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
46
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
47
|
+
in the Software without restriction, including without limitation the rights
|
|
48
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
49
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
50
|
+
furnished to do so, subject to the following conditions:
|
|
51
|
+
|
|
52
|
+
The above copyright notice and this permission notice shall be included in all
|
|
53
|
+
copies or substantial portions of the Software.
|
|
54
|
+
|
|
55
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
56
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
57
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
58
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
59
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
60
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
61
|
+
SOFTWARE.
|
|
62
|
+
|
|
63
|
+
https://github.com/uiwjs/react-codemirror
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
-------------------------------------------------------------------------------
|
|
67
|
+
cm6-graphql, graphql, graphql-language-service
|
|
68
|
+
-------------------------------------------------------------------------------
|
|
69
|
+
MIT License
|
|
70
|
+
|
|
71
|
+
Copyright (c) 2021 GraphQL Contributors
|
|
72
|
+
|
|
73
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
74
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
75
|
+
in the Software without restriction, including without limitation the rights
|
|
76
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
77
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
78
|
+
furnished to do so, subject to the following conditions:
|
|
79
|
+
|
|
80
|
+
The above copyright notice and this permission notice shall be included in all
|
|
81
|
+
copies or substantial portions of the Software.
|
|
82
|
+
|
|
83
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
84
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
85
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
86
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
87
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
88
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
89
|
+
SOFTWARE.
|
|
90
|
+
|
|
91
|
+
https://github.com/graphql/graphiql
|
|
92
|
+
https://github.com/graphql/graphql-js
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
-------------------------------------------------------------------------------
|
|
96
|
+
@babel/runtime
|
|
97
|
+
-------------------------------------------------------------------------------
|
|
98
|
+
MIT License
|
|
99
|
+
|
|
100
|
+
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
101
|
+
|
|
102
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
103
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
104
|
+
in the Software without restriction, including without limitation the rights
|
|
105
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
106
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
107
|
+
furnished to do so, subject to the following conditions:
|
|
108
|
+
|
|
109
|
+
The above copyright notice and this permission notice shall be included in all
|
|
110
|
+
copies or substantial portions of the Software.
|
|
111
|
+
|
|
112
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
113
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
114
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
115
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
116
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
117
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
118
|
+
SOFTWARE.
|
|
119
|
+
|
|
120
|
+
https://babel.dev
|
package/app.plugin.js
CHANGED