mirror of
https://github.com/duhanbalci/dexpr.git
synced 2026-07-01 16:19:16 +00:00
initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "(OSX) Launch",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/target/debug/rust-expr",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceRoot}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
90
CLAUDE.md
Normal file
90
CLAUDE.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
dexpr is an embeddable expression evaluator and bytecode VM written in Rust. It parses expressions and simple scripts (`.dexpr` files), compiles to bytecode, and executes on a register-based virtual machine. Designed to be embedded in other projects as a rule engine, formula evaluator, or expression calculator.
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run tests
|
||||||
|
cargo test
|
||||||
|
|
||||||
|
# Run benchmarks
|
||||||
|
cargo bench --bench my_benchmark
|
||||||
|
|
||||||
|
# Run the main program (executes basic_long.dexpr by default)
|
||||||
|
cargo run --release
|
||||||
|
|
||||||
|
# Profile with samply
|
||||||
|
cargo build --profile profiling
|
||||||
|
samply record ./target/profiling/dexpr
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The pipeline flows: **Parser → AST → Compiler → Bytecode → VM**
|
||||||
|
|
||||||
|
### Core Modules
|
||||||
|
|
||||||
|
- **`parser/`**: PEG-based parser (`grammar.rs`) that produces AST nodes
|
||||||
|
- **`ast/`**: Expression (`expr.rs`), statement (`stmt.rs`), and value (`value.rs`) types
|
||||||
|
- **`compiler.rs`**: Transforms AST into bytecode; single-pass, globals-only, register allocation
|
||||||
|
- **`bytecode.rs`**: `BytecodeWriter` for compilation, `BytecodeReader` for VM consumption
|
||||||
|
- **`opcodes.rs`**: Defines `OpCodeByte` enum and `Register` type
|
||||||
|
- **`vm/vm.rs`**: Register-based VM with global variable support; executes bytecode
|
||||||
|
|
||||||
|
### Key Types
|
||||||
|
|
||||||
|
- `Value` (ast/value.rs): Runtime values (Number using rust_decimal, String, Boolean, Object using indexmap, etc.)
|
||||||
|
- `Compiler`: Stateful compiler with register allocation
|
||||||
|
- `VM<'a>`: Bytecode interpreter with global variable support via `set_global`/`get_global`
|
||||||
|
|
||||||
|
### Typical Usage Pattern
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dexpr::{ast::value::Value, compiler::Compiler, parser, vm::VM};
|
||||||
|
|
||||||
|
let ast = parser::program(source_code)?;
|
||||||
|
let mut compiler = Compiler::new();
|
||||||
|
let bytecode = compiler.compile(ast)?;
|
||||||
|
let mut vm = VM::new(&bytecode);
|
||||||
|
vm.set_global("input", Value::Number(dec!(42)));
|
||||||
|
vm.register_function("getRate", |args| Ok(Value::Number(dec!(34.5))));
|
||||||
|
let result = vm.execute()?; // Returns last expression's value
|
||||||
|
// Or use globals: let output = vm.get_global("output");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Language Features
|
||||||
|
|
||||||
|
The dexpr language supports:
|
||||||
|
- If/else conditionals with `if ... then ... else ... end`
|
||||||
|
- String methods (e.g., `.upper()`, `.lower()`, `.trim()`, `.trimStart()`, `.trimEnd()`, `.split()`, `.replace()`, `.contains()`, `.startsWith()`, `.endsWith()`, `.length`, `.charAt()`, `.substring()`)
|
||||||
|
- Arithmetic (`+`, `-`, `*`, `/`, `%`, `**`), comparison, and logical operators
|
||||||
|
- `in` operator for membership testing (`"finans" in categories`, `5 in numbers`, `"hello" in "hello world"`, `"key" in obj`)
|
||||||
|
- Compound assignments (`+=`, `-=`, `*=`, `/=`, `%=`)
|
||||||
|
- Built-in `log()` function for output and `rand(min, max)` for random integers
|
||||||
|
- External (host) function registration via `vm.register_function()`
|
||||||
|
- External (host) method registration via `vm.register_method()`
|
||||||
|
- Expression return value: `execute()` returns the last expression's value
|
||||||
|
- Line comments (`//`) and block comments (`/* */`)
|
||||||
|
- Lists: `NumberList` and `StringList` types with methods (`sum`, `avg`, `min`, `max`, `first`, `last`, `get`, `join`, `contains`, `indexOf`, `slice`, `reverse`, `sort`, `isEmpty`, etc.)
|
||||||
|
- Objects: `Object` type (provided externally via `set_global`) with property access (`obj.field`), nested access (`obj.a.b`), property assignment (`obj.field = value`), and methods (`keys()`, `values()`, `length()`, `contains(key)`, `get(key)`)
|
||||||
|
|
||||||
|
## Detailed Module Documentation
|
||||||
|
|
||||||
|
**IMPORTANT:** Before making any changes to the codebase, read the relevant documentation files in the `docs/` folder to understand how that module works in detail. After making changes to any module, update the corresponding documentation file to keep it in sync.
|
||||||
|
|
||||||
|
- **[docs/architecture.md](docs/architecture.md)** — Overall architecture, pipeline, design decisions, dependencies
|
||||||
|
- **[docs/ast.md](docs/ast.md)** — AST module: Expr, Stmt, Value types, Span, serialization format
|
||||||
|
- **[docs/parser.md](docs/parser.md)** — Parser: PEG grammar rules, operator precedence, reserved keywords
|
||||||
|
- **[docs/opcodes.md](docs/opcodes.md)** — Opcodes: full instruction set with hex values and categories
|
||||||
|
- **[docs/bytecode.md](docs/bytecode.md)** — Bytecode: BytecodeWriter/Reader API, data format, disassembler
|
||||||
|
- **[docs/compiler.md](docs/compiler.md)** — Compiler: single-pass compilation, register allocation, label/jump system
|
||||||
|
- **[docs/vm.md](docs/vm.md)** — VM: execution loop, opcode handlers, error types, DebugInfo
|
||||||
|
- **[docs/language_info.md](docs/language_info.md)** — Language Info: editor metadata generation, JSON format, host integration
|
||||||
|
- **[docs/editor.md](docs/editor.md)** — Editor: CodeMirror 6 language support, Lezer grammar, type-aware autocomplete
|
||||||
|
|
||||||
|
**Rule:** Any code change that modifies the behavior, API, or structure of a module MUST be accompanied by an update to the corresponding `docs/` file. Documentation and code must always stay in sync.
|
||||||
1297
Cargo.lock
generated
Normal file
1297
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
41
Cargo.toml
Normal file
41
Cargo.toml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
[package]
|
||||||
|
name = "dexpr"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
incremental = true
|
||||||
|
debug = true
|
||||||
|
lto = "fat"
|
||||||
|
codegen-units = 1
|
||||||
|
|
||||||
|
[profile.profiling]
|
||||||
|
inherits = "release"
|
||||||
|
debug = true
|
||||||
|
split-debuginfo = "packed"
|
||||||
|
opt-level = 3
|
||||||
|
overflow-checks = false
|
||||||
|
panic = "unwind"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rust_decimal = { version = "1.41.0", features = ["maths"] }
|
||||||
|
rust_decimal_macros = "1.40.0"
|
||||||
|
rand = "0.10.0"
|
||||||
|
smallvec = "1.15.1"
|
||||||
|
rustc-hash = "2.1.2"
|
||||||
|
peg = "0.8.5"
|
||||||
|
smol_str = "0.3.6"
|
||||||
|
micromap = "0.3.0"
|
||||||
|
thiserror = "2.0.18"
|
||||||
|
bumpalo = "3.20.2"
|
||||||
|
indexmap = "2"
|
||||||
|
serde_json = "1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = { version = "0.8.2", features = ["html_reports"] }
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "my_benchmark"
|
||||||
|
harness = false
|
||||||
69
benches/my_benchmark.rs
Normal file
69
benches/my_benchmark.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
|
use dexpr::{ast::value::Value, compiler::Compiler, parser, vm::VM};
|
||||||
|
use rust_decimal_macros::dec;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
|
// 1. Parser Benchmark
|
||||||
|
c.bench_function("parser_long", |b| {
|
||||||
|
let input = include_str!("../src/bench_long.dexpr");
|
||||||
|
b.iter(|| {
|
||||||
|
let _ = parser::program(input).unwrap();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Compiler Benchmark
|
||||||
|
c.bench_function("compiler_long", |b| {
|
||||||
|
let input = include_str!("../src/bench_long.dexpr");
|
||||||
|
let ast = parser::program(input).unwrap();
|
||||||
|
b.iter(|| {
|
||||||
|
let mut compiler = Compiler::new();
|
||||||
|
let _ = compiler.compile(ast.clone()).unwrap();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. VM Benchmarks
|
||||||
|
|
||||||
|
// basic_long.dexpr benchmark
|
||||||
|
c.bench_function("vm_basic_long", |b| {
|
||||||
|
let input = include_str!("../src/basic_long.dexpr");
|
||||||
|
let ast = parser::program(input).unwrap();
|
||||||
|
let mut compiler = Compiler::new();
|
||||||
|
let bytecode = compiler.compile(ast).unwrap();
|
||||||
|
b.iter(|| {
|
||||||
|
let mut vm = VM::new(&bytecode);
|
||||||
|
vm.set_global("test", Value::Number(dec!(3)));
|
||||||
|
let _ = vm.execute().unwrap();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Long code benchmark (using bench_long.dexpr)
|
||||||
|
c.bench_function("vm_long", |b| {
|
||||||
|
let input = include_str!("../src/bench_long.dexpr");
|
||||||
|
let ast = parser::program(input).unwrap();
|
||||||
|
let mut compiler = Compiler::new();
|
||||||
|
let bytecode = compiler.compile(ast).unwrap();
|
||||||
|
b.iter(|| {
|
||||||
|
let mut vm = VM::new(&bytecode);
|
||||||
|
let _ = vm.execute().unwrap();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Short code benchmark
|
||||||
|
c.bench_function("vm_short", |b| {
|
||||||
|
let input = "5.12 + test * 1.5";
|
||||||
|
let ast = parser::program(input).unwrap();
|
||||||
|
let mut compiler = Compiler::new();
|
||||||
|
let bytecode = compiler.compile(ast).unwrap();
|
||||||
|
let test_val = dec!(100);
|
||||||
|
b.iter(|| {
|
||||||
|
let mut vm = VM::new(&bytecode);
|
||||||
|
vm.set_global("test", Value::Number(test_val));
|
||||||
|
let _ = vm.execute().unwrap();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, criterion_benchmark);
|
||||||
|
criterion_main!(benches);
|
||||||
91
docs/architecture.md
Normal file
91
docs/architecture.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Genel Mimari
|
||||||
|
|
||||||
|
dexpr, kaynak kodu parse edip bytecode'a derleyen ve register tabanlı bir VM üzerinde çalıştıran bir ifade değerlendirici (expression evaluator) ve bytecode VM'dir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pipeline
|
||||||
|
|
||||||
|
```
|
||||||
|
Kaynak Kod (.dexpr)
|
||||||
|
↓
|
||||||
|
[PARSER] ← PEG tabanlı gramer kuralları
|
||||||
|
↓
|
||||||
|
AST (Expr, Stmt, Value)
|
||||||
|
↓
|
||||||
|
[COMPILER] ← Tek geçişli derleme
|
||||||
|
↓
|
||||||
|
Bytecode (ham byte dizisi)
|
||||||
|
↓
|
||||||
|
[VM] ← 8 register, global'ler
|
||||||
|
↓
|
||||||
|
Sonuç (veya kaynak konum bilgili hata)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Temel Tasarım Kararları
|
||||||
|
|
||||||
|
1. **Register tabanlı VM:** Stack tabanlı VM'lere göre daha az komut, daha hızlı çalışma
|
||||||
|
2. **8 register limiti:** Basitlik ve hız arasında denge
|
||||||
|
3. **Tek geçişli derleme:** Fonksiyon desteği kaldırıldığı için iki geçişe gerek yok
|
||||||
|
4. **Label tabanlı atlamalar:** Son geçişte çözümlenir
|
||||||
|
5. **Span izleme:** Derleme ve çalışma zamanı hataları kaynak kod konumunu gösterir
|
||||||
|
6. **Value serileştirme:** Sabitler doğrudan bytecode'a gömülür
|
||||||
|
7. **Object tipi:** `IndexMap<SmolStr, Value>` tabanlı anahtar-değer nesneleri; özellik erişimi (`obj.field`), iç içe atama (`a.b.c = expr`) ve built-in metodlar (`keys`, `values`, `contains`, `get`, `length`) desteklenir
|
||||||
|
8. **Sadece global değişkenler:** Tüm değişkenler global scope'ta; host uygulamadan `set_global` ile değer aktarılır
|
||||||
|
9. **Bytecode cache:** Compile edilmiş bytecode saklanıp farklı global değerlerle tekrar çalıştırılabilir
|
||||||
|
10. **Harici fonksiyonlar:** Host fonksiyonları VM'de isimle kayıt edilir, runtime'da HashMap lookup ile çözümlenir
|
||||||
|
11. **Harici metodlar:** Tipe özel host metodları eklenebilir, built-in metodlar bulunamazsa kontrol edilir
|
||||||
|
12. **Expression return:** `execute()` son ExprStmt'ın değerini döndürür — tek satır formüller doğrudan sonuç verir
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tipik Kullanım
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dexpr::{ast::value::Value, compiler::Compiler, parser, vm::VM};
|
||||||
|
|
||||||
|
// 1. Parse
|
||||||
|
let ast = parser::program(source_code)?;
|
||||||
|
|
||||||
|
// 2. Compile
|
||||||
|
let mut compiler = Compiler::new();
|
||||||
|
let bytecode = compiler.compile(ast)?;
|
||||||
|
|
||||||
|
// 3. Execute (bytecode cache'lenip tekrar kullanılabilir)
|
||||||
|
let mut vm = VM::new(&bytecode);
|
||||||
|
vm.set_global("input", Value::Number(dec!(42)));
|
||||||
|
vm.register_function("getRate", |args| { Ok(Value::Number(dec!(34.5))) });
|
||||||
|
let result = vm.execute()?; // Son expression'ın değerini döndürür
|
||||||
|
// veya: let output = vm.get_global("output");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bağımlılıklar
|
||||||
|
|
||||||
|
| Crate | Kullanım |
|
||||||
|
|-------|----------|
|
||||||
|
| `rust_decimal` | Keyfi hassasiyetli ondalık aritmetik |
|
||||||
|
| `peg` | PEG tabanlı parser üreteci |
|
||||||
|
| `smol_str` | Kısa string'ler için optimize edilmiş tip |
|
||||||
|
| `micromap` | Kompakt hashmap (global değişkenler için) |
|
||||||
|
| `bumpalo` | Bump allocator (hızlı bellek ayırma) |
|
||||||
|
| `thiserror` | Hata türleri için derive makrosu |
|
||||||
|
| `rustc-hash` | Hızlı hash fonksiyonu |
|
||||||
|
| `smallvec` | Stack-allocated vektörler |
|
||||||
|
| `indexmap` | Sıralı hashmap (Object tipi için) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modül Referansları
|
||||||
|
|
||||||
|
- [AST Modülü](ast.md) — İfadeler, deyimler, değer türleri
|
||||||
|
- [Parser Modülü](parser.md) — Gramer kuralları, ayrıştırma
|
||||||
|
- [Opcodes Modülü](opcodes.md) — Bytecode komut seti
|
||||||
|
- [Bytecode Modülü](bytecode.md) — Serileştirme, disassembler
|
||||||
|
- [Compiler Modülü](compiler.md) — AST → bytecode dönüşümü
|
||||||
|
- [VM Modülü](vm.md) — Sanal makine, çalıştırma
|
||||||
|
- [Language Info Modülü](language_info.md) — Editör metadata üretimi
|
||||||
|
- [Editor Modülü](editor.md) — CodeMirror 6 dil desteği (codemirror-lang-dexpr)
|
||||||
115
docs/ast.md
Normal file
115
docs/ast.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# AST (Abstract Syntax Tree) Modülü
|
||||||
|
|
||||||
|
**Konum:** `src/ast/`
|
||||||
|
|
||||||
|
AST modülü, parser tarafından üretilen ve compiler tarafından tüketilen ağaç yapısını tanımlar. Üç alt modülden oluşur: `expr.rs`, `stmt.rs`, `value.rs`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Span & Spanned
|
||||||
|
|
||||||
|
**Dosya:** `src/ast/expr.rs`
|
||||||
|
|
||||||
|
`Span`, kaynak koddaki bir konumu (satır, sütun) temsil eder. 1-indexed'tir.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Span { line: u32, column: u32 }
|
||||||
|
```
|
||||||
|
|
||||||
|
`Spanned<T>`, herhangi bir AST node'unu kaynak kod konumuyla eşleştirir:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Spanned<T> { node: T, span: Span }
|
||||||
|
```
|
||||||
|
|
||||||
|
`dummy()` metodu test ve internal kullanım için varsayılan konum oluşturur.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Expr (İfadeler)
|
||||||
|
|
||||||
|
**Dosya:** `src/ast/expr.rs`
|
||||||
|
**Type alias:** `SpannedExpr = Spanned<Expr>`
|
||||||
|
|
||||||
|
`Expr` enum'u tüm ifade türlerini kapsar:
|
||||||
|
|
||||||
|
| Variant | Açıklama | Örnek |
|
||||||
|
|---------|----------|-------|
|
||||||
|
| `Value(Value)` | Sabit değer (literal) | `42`, `"hello"`, `true` |
|
||||||
|
| `Variable(SmolStr)` | Değişken referansı | `x`, `result` |
|
||||||
|
| `BinaryOp(Box<Expr>, Op, Box<Expr>)` | İkili operasyon | `a + b`, `x > 5` |
|
||||||
|
| `UnaryOp(Op, Box<Expr>)` | Tekli operasyon | `-x`, `!flag` |
|
||||||
|
| `FunctionCall(SmolStr, Vec<Expr>)` | Built-in fonksiyon çağrısı | `log(x)` |
|
||||||
|
| `MethodCall(Box<Expr>, SmolStr, Vec<Expr>)` | Metod çağrısı | `name.upper()`, `text.split(",")` |
|
||||||
|
| `PropertyAccess(Box<Expr>, SmolStr)` | Özellik erişimi | `obj.field`, `person.name` |
|
||||||
|
|
||||||
|
> **Not:** `FunctionCall` hem built-in (`log`) hem de harici (host) fonksiyonlar için kullanılır. Built-in olmayan fonksiyonlar `CallExternal` opcode'u ile derlenir ve VM tarafından runtime'da çözümlenir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Op (Operatörler)
|
||||||
|
|
||||||
|
**Dosya:** `src/ast/expr.rs`
|
||||||
|
|
||||||
|
| Kategori | Operatörler |
|
||||||
|
|----------|-------------|
|
||||||
|
| Aritmetik | `Add`, `Sub`, `Mul`, `Div`, `Mod`, `Pow` |
|
||||||
|
| Karşılaştırma | `Lt`, `Lte`, `Gt`, `Gte`, `Eq`, `Neq` |
|
||||||
|
| Boolean | `And`, `Or`, `Not` |
|
||||||
|
| Üyelik | `In` (değer listede/string'de var mı) |
|
||||||
|
| Tekli | `Neg` (negatif) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stmt (İfadeler/Deyimler)
|
||||||
|
|
||||||
|
**Dosya:** `src/ast/stmt.rs`
|
||||||
|
**Type alias:** `SpannedStmt = Spanned<Stmt>`
|
||||||
|
|
||||||
|
| Variant | Açıklama | Sözdizimi |
|
||||||
|
|---------|----------|-----------|
|
||||||
|
| `Assignment(SmolStr, Box<Expr>)` | Değişken ataması | `x = 5` |
|
||||||
|
| `ExprStmt(Box<Expr>)` | İfade deyimi | `log(x)` |
|
||||||
|
| `If(Box<Expr>, Vec<Stmt>, Option<Vec<Stmt>>)` | Koşullu deyim | `if x > 0 then ... end` |
|
||||||
|
| `PropertyAssignment(SmolStr, Vec<SmolStr>, Box<Expr>)` | Özellik ataması | `a.b.c = expr` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Value (Çalışma Zamanı Değerleri)
|
||||||
|
|
||||||
|
**Dosya:** `src/ast/value.rs`
|
||||||
|
|
||||||
|
| Variant | Rust Tipi | Açıklama |
|
||||||
|
|---------|-----------|----------|
|
||||||
|
| `Null` | - | Boş değer |
|
||||||
|
| `Number(Decimal)` | `rust_decimal::Decimal` | Keyfi hassasiyetli ondalık sayı |
|
||||||
|
| `String(SmolStr)` | `smol_str::SmolStr` | Optimize edilmiş string |
|
||||||
|
| `Boolean(bool)` | `bool` | Mantıksal değer |
|
||||||
|
| `NumberList(Vec<Decimal>)` | `Vec<Decimal>` | Sayı listesi |
|
||||||
|
| `StringList(Vec<SmolStr>)` | `Vec<SmolStr>` | String listesi |
|
||||||
|
| `Object(IndexMap<SmolStr, Value>)` | `IndexMap<SmolStr, Value>` | Anahtar-değer nesnesi |
|
||||||
|
|
||||||
|
### Serileştirme
|
||||||
|
|
||||||
|
Her `Value` bytecode'a gömülebilir. Serileştirme formatı:
|
||||||
|
|
||||||
|
1. **Tip etiketi** (1 byte): `NULL=0x00`, `NUMBER=0x01`, `STRING=0x02`, `BOOLEAN=0x03`, `NUMBER_LIST=0x04`, `STRING_LIST=0x05`, `OBJECT=0x06`
|
||||||
|
2. **Veri:**
|
||||||
|
- Number: 16 byte (Decimal serialization)
|
||||||
|
- String: 2-byte uzunluk + UTF-8 bytes
|
||||||
|
- Boolean: 1 byte (0 veya 1)
|
||||||
|
- NumberList: 2-byte count + her sayı için 16 byte
|
||||||
|
- StringList: 2-byte count + her string için (2-byte uzunluk + bytes)
|
||||||
|
- Object: 2-byte entry count + her girdi için (anahtar: 2-byte uzunluk + bytes, değer: rekürsif serialize)
|
||||||
|
|
||||||
|
`serialize()` ve `deserialize()` metodları bu dönüşümü gerçekleştirir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modüller Arası İlişki
|
||||||
|
|
||||||
|
```
|
||||||
|
Parser --> Expr, Stmt, Value (AST üretir)
|
||||||
|
Compiler <-- Expr, Stmt, Value (AST tüketir, bytecode üretir)
|
||||||
|
VM <-- Value (çalışma zamanında değer olarak kullanılır)
|
||||||
|
```
|
||||||
79
docs/bytecode.md
Normal file
79
docs/bytecode.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Bytecode Modülü
|
||||||
|
|
||||||
|
**Konum:** `src/bytecode.rs`
|
||||||
|
|
||||||
|
Bytecode'un serileştirilmesi (yazma) ve deserileştirilmesi (okuma) işlemlerini sağlar. Compiler bytecode üretirken `BytecodeWriter`'ı, VM çalıştırırken `BytecodeReader`'ı kullanır.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## BytecodeWriter
|
||||||
|
|
||||||
|
Compiler tarafından bytecode üretmek için kullanılır.
|
||||||
|
|
||||||
|
| Metod | Açıklama |
|
||||||
|
|-------|----------|
|
||||||
|
| `new()` | Boş writer oluştur |
|
||||||
|
| `write_byte(u8)` | Tek byte yaz |
|
||||||
|
| `write_u16(u16)` | Big-endian 16-bit tamsayı yaz |
|
||||||
|
| `write_u32(u32)` | Big-endian 32-bit tamsayı yaz |
|
||||||
|
| `write_register(u8)` | Register indeksi yaz |
|
||||||
|
| `write_string(SmolStr)` | String yaz (2-byte uzunluk + UTF-8) |
|
||||||
|
| `write_value(Value)` | Serileştirilmiş Value yaz |
|
||||||
|
| `position() -> usize` | Geçerli bytecode pozisyonu |
|
||||||
|
| `bytecode() -> &[u8]` | Bytecode'un immutable view'ı |
|
||||||
|
| `into_bytecode() -> Vec<u8>` | Writer'ı tüket, byte vektörü döndür |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## BytecodeReader
|
||||||
|
|
||||||
|
VM tarafından bytecode'u okumak için kullanılır.
|
||||||
|
|
||||||
|
| Metod | Açıklama |
|
||||||
|
|-------|----------|
|
||||||
|
| `new(bytecode)` | Bytecode'dan reader oluştur |
|
||||||
|
| `read_byte() -> Result<u8>` | Tek byte oku |
|
||||||
|
| `read_u16() -> Result<u16>` | Big-endian 16-bit tamsayı oku |
|
||||||
|
| `read_u32() -> Result<u32>` | Big-endian 32-bit tamsayı oku |
|
||||||
|
| `read_register() -> Result<u8>` | Register indeksi oku |
|
||||||
|
| `read_string() -> Result<SmolStr>` | String oku |
|
||||||
|
| `read_value() -> Result<Value>` | Value deserileştir ve oku |
|
||||||
|
| `position() -> usize` | Geçerli okuma pozisyonu |
|
||||||
|
| `set_position(usize)` | Pozisyona atla (bounds check ile) |
|
||||||
|
| `remaining() -> usize` | Kalan byte sayısı |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Veri Formatı
|
||||||
|
|
||||||
|
Tüm çok-byte değerler **big-endian** formatında saklanır.
|
||||||
|
|
||||||
|
### String Formatı
|
||||||
|
```
|
||||||
|
[2 bytes: uzunluk (u16)] [N bytes: UTF-8 veri]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Value Formatı
|
||||||
|
```
|
||||||
|
[1 byte: tip etiketi] [N bytes: tipe göre veri]
|
||||||
|
```
|
||||||
|
|
||||||
|
Detaylı Value serileştirme formatı için [AST dokümantasyonuna](ast.md#serileştirme) bakın.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bytecode Dump (Disassembler)
|
||||||
|
|
||||||
|
**Konum:** `src/bytecode_dump.rs`
|
||||||
|
|
||||||
|
`disassemble_bytecode(bytecode) -> Vec<String>` fonksiyonu bytecode'u insan okunabilir formata çevirir:
|
||||||
|
|
||||||
|
```
|
||||||
|
0000: LoadConst r0, 42
|
||||||
|
0008: StoreGlobal "x", r0
|
||||||
|
000d: LoadGlobal r0, "x"
|
||||||
|
0014: Log r0
|
||||||
|
0016: End
|
||||||
|
```
|
||||||
|
|
||||||
|
Bu araç debug ve geliştirme sürecinde bytecode'u incelemek için kullanılır.
|
||||||
150
docs/compiler.md
Normal file
150
docs/compiler.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# Compiler Modülü
|
||||||
|
|
||||||
|
**Konum:** `src/compiler.rs`
|
||||||
|
|
||||||
|
AST'yi bytecode'a dönüştürür. Tek geçişli (single-pass) derleme yapar. Tüm değişkenler global scope'tadır.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Konfigürasyon
|
||||||
|
|
||||||
|
- `MAX_REGISTERS = 8` — Hesaplama için kullanılabilir register sayısı
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hata Türleri (CompileError)
|
||||||
|
|
||||||
|
| Hata | Açıklama |
|
||||||
|
|------|----------|
|
||||||
|
| `UndefinedFunction(SmolStr)` | Tanımlanmamış fonksiyon (built-in dışı çağrı) |
|
||||||
|
| `RegisterLimitExceeded` | Register limiti aşıldı |
|
||||||
|
| `InvalidExpression(String)` | Geçersiz ifade |
|
||||||
|
| `InvalidStatement(String)` | Geçersiz deyim |
|
||||||
|
| `BytecodeError(String)` | Bytecode üretim hatası |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Compiler Yapısı
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Compiler {
|
||||||
|
writer: BytecodeWriter,
|
||||||
|
used_registers: Vec<bool>,
|
||||||
|
|
||||||
|
// Jump address resolution
|
||||||
|
pending_jumps: Vec<(usize, usize)>,
|
||||||
|
labels: HashMap<usize, usize>,
|
||||||
|
next_label: usize,
|
||||||
|
|
||||||
|
// Debug info generation
|
||||||
|
debug_info: DebugInfo,
|
||||||
|
current_span: Span,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Derleme Akışı
|
||||||
|
|
||||||
|
### Ana Derleme: `compile(statements) -> Vec<u8>`
|
||||||
|
|
||||||
|
Tek geçişli derleme süreci:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Deyimleri sırayla derle
|
||||||
|
2. End opcode'u yaz
|
||||||
|
3. Atlama adreslerini çözümle (resolve_jumps)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kaynak Koddan Derleme: `compile_from_source(source) -> (Vec<u8>, DebugInfo)`
|
||||||
|
|
||||||
|
Parse ile birlikte pozisyon bilgisi de toplar ve `DebugInfo` üretir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deyim Derleme
|
||||||
|
|
||||||
|
### Assignment (Atama)
|
||||||
|
|
||||||
|
1. İfadeyi register'a derle
|
||||||
|
2. `StoreGlobal` emit et (tüm değişkenler global)
|
||||||
|
|
||||||
|
### If Statement (Koşullu Deyim)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Koşulu register'a derle
|
||||||
|
2. Else ve end için label oluştur
|
||||||
|
3. JumpIfFalse → else label
|
||||||
|
4. Then dalını derle
|
||||||
|
5. Jump → end label
|
||||||
|
6. Else label'ını set et, else dalını derle
|
||||||
|
7. End label'ını set et
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## İfade Derleme
|
||||||
|
|
||||||
|
### Value (Sabit Değer)
|
||||||
|
- Register ayır → `LoadConst` emit et
|
||||||
|
|
||||||
|
### Variable (Değişken)
|
||||||
|
- Register ayır → `LoadGlobal` emit et
|
||||||
|
|
||||||
|
### BinaryOp (İkili Operasyon)
|
||||||
|
1. Sol operandı register'a derle
|
||||||
|
2. Sağ operandı register'a derle
|
||||||
|
3. Sonuç register'ı ayır
|
||||||
|
4. Uygun opcode'u emit et (Add, Sub, Mul, vs.)
|
||||||
|
5. **Özel durum:** String + String → `Concat` kullanılır
|
||||||
|
6. Operand register'ları serbest bırak
|
||||||
|
|
||||||
|
### UnaryOp (Tekli Operasyon)
|
||||||
|
1. Operandı register'a derle
|
||||||
|
2. Sonuç register'ı ayır
|
||||||
|
3. `Neg` veya `Not` emit et
|
||||||
|
|
||||||
|
### FunctionCall (Fonksiyon Çağrısı)
|
||||||
|
|
||||||
|
- `log` built-in fonksiyonu: Argümanları derle → `Log` emit et → Null register döndür
|
||||||
|
- Diğer fonksiyonlar: `CallExternal` opcode emit edilir (VM tarafından runtime'da çözümlenir)
|
||||||
|
|
||||||
|
### ExprStmt (İfade Deyimi)
|
||||||
|
- İfadeyi derle → `SetResult` emit et → Register'ı serbest bırak
|
||||||
|
- `SetResult`, VM'in `execute()` dönüş değerini belirler (son ExprStmt kazanır)
|
||||||
|
|
||||||
|
### MethodCall (Metod Çağrısı)
|
||||||
|
- Nesneyi register'a derle
|
||||||
|
- Argümanları derle
|
||||||
|
- `MethodCall` emit et (sonuç, nesne, metod adı, argüman sayısı, argüman register'ları)
|
||||||
|
|
||||||
|
### PropertyAccess (Özellik Erişimi)
|
||||||
|
- Nesneyi register'a derle
|
||||||
|
- `GetProperty` emit et (hedef register, nesne register, özellik adı string)
|
||||||
|
|
||||||
|
### PropertyAssignment (Özellik Ataması)
|
||||||
|
- İç içe özellik zinciri (`a.b.c = expr`) için:
|
||||||
|
1. Kök değişkeni `LoadGlobal` ile yükle
|
||||||
|
2. Ara özellikler için `GetProperty` zinciri emit et
|
||||||
|
3. Son özellik için `SetProperty` emit et
|
||||||
|
4. Değiştirilmiş kök nesneyi `StoreGlobal` ile geri yaz
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Register Yönetimi
|
||||||
|
|
||||||
|
- `allocate_register() -> u8` — İlk boş register'ı bul, yoksa hata
|
||||||
|
- `free_register(reg)` — Register'ı kullanılabilir olarak işaretle
|
||||||
|
- Toplam 8 register limiti var
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Label ve Jump Yönetimi
|
||||||
|
|
||||||
|
| Metod | Açıklama |
|
||||||
|
|-------|----------|
|
||||||
|
| `create_label() -> usize` | Benzersiz label ID üret |
|
||||||
|
| `set_label(id)` | Label'ın bytecode pozisyonunu kaydet |
|
||||||
|
| `emit_jump_address(label) -> usize` | Placeholder yaz, çözümleme için kaydet |
|
||||||
|
| `emit_jump(label)` | Koşulsuz atlama emit et |
|
||||||
|
| `resolve_jumps()` | Tüm placeholder'ları gerçek adreslerle doldur |
|
||||||
266
docs/editor.md
Normal file
266
docs/editor.md
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
# Editor Modülü (codemirror-lang-dexpr)
|
||||||
|
|
||||||
|
**Konum:** `editor/`
|
||||||
|
|
||||||
|
CodeMirror 6 için dexpr dil desteği kütüphanesi. Syntax highlighting, tip-bazlı autocomplete ve error-tolerant parsing sağlar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mimari
|
||||||
|
|
||||||
|
```
|
||||||
|
editor/
|
||||||
|
src/
|
||||||
|
dexpr.grammar ← Lezer gramer dosyası (kaynak)
|
||||||
|
parser.js ← Lezer tarafından üretilen parser (generated)
|
||||||
|
parser.terms.js ← Token tanımları (generated)
|
||||||
|
tokens.ts ← External tokenizer (else if → tek token)
|
||||||
|
language.ts ← LRLanguage tanımı + syntax highlighting tag'leri
|
||||||
|
highlight.ts ← Varsayılan renk teması
|
||||||
|
completions.ts ← Autocomplete: tip çıkarımı + metadata bazlı öneriler
|
||||||
|
index.ts ← Ana export: dexpr() fonksiyonu
|
||||||
|
demo.ts ← Test sayfası kaynak kodu
|
||||||
|
demo.html ← Test sayfası
|
||||||
|
dexpr.grammar ← (src altındaki asıl dosya)
|
||||||
|
```
|
||||||
|
|
||||||
|
### İki Parser Stratejisi
|
||||||
|
|
||||||
|
| Taraf | Parser | Amaç |
|
||||||
|
|-------|--------|------|
|
||||||
|
| **Rust** (execution) | PEG (`peg` crate) | AST üretimi → derleme → VM çalıştırma |
|
||||||
|
| **Editor** (web) | Lezer | Syntax highlighting, error recovery, autocomplete |
|
||||||
|
|
||||||
|
Dil küçük olduğundan (7 keyword, ~20 operatör) iki gramer dosyasını sync tutmak kolaydır.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lezer Grammar
|
||||||
|
|
||||||
|
**Dosya:** `src/dexpr.grammar`
|
||||||
|
|
||||||
|
### Parse Kuralları
|
||||||
|
|
||||||
|
| Kural | Açıklama |
|
||||||
|
|-------|----------|
|
||||||
|
| `Program` | `statement*` — üst düzey kural |
|
||||||
|
| `IfStatement` | `if expr then stmts (else if expr then stmts)* (else stmts)? end` |
|
||||||
|
| `Assignment` | `VariableName AssignOp expression` veya `VariableName (.PropertyName)+ AssignOp expression` |
|
||||||
|
| `PropertyAccess` | `expression.PropertyName` — nesne özellik erişimi |
|
||||||
|
| `ExprStatement` | Bağımsız ifade |
|
||||||
|
| `BinaryExpression` | İkili operatörler, öncelik sırasıyla |
|
||||||
|
| `UnaryExpression` | Tekli `-` ve `!` |
|
||||||
|
| `MethodCall` | `expression.PropertyName(args)` |
|
||||||
|
| `FunctionCall` | `VariableName(args)` |
|
||||||
|
| `ParenExpression` | `(expression)` |
|
||||||
|
|
||||||
|
### Operatör Önceliği (düşükten yükseğe)
|
||||||
|
|
||||||
|
1. `||` — mantıksal OR
|
||||||
|
2. `&&` — mantıksal AND
|
||||||
|
3. `==`, `!=`, `<`, `<=`, `>`, `>=`, `in` — karşılaştırma
|
||||||
|
4. `+`, `-` — toplama/çıkarma
|
||||||
|
5. `*`, `/`, `%` — çarpma/bölme/mod
|
||||||
|
6. `**` — üs alma (sağdan birleşimli)
|
||||||
|
7. `-`, `!` — tekli operatörler (prefix)
|
||||||
|
8. `.method()` — metod çağrısı
|
||||||
|
9. `name()` — fonksiyon çağrısı
|
||||||
|
|
||||||
|
### External Tokenizer
|
||||||
|
|
||||||
|
**Dosya:** `src/tokens.ts`
|
||||||
|
|
||||||
|
`else if` iki ayrı keyword olarak yazılır ama Lezer'da tek token olarak tanınır (`elseIf`). External tokenizer `else` + boşluk + `if` dizisini tespit edip tek token üretir. Bu sayede `else if` zinciri ile nested `if` arasındaki belirsizlik (ambiguity) ortadan kalkar.
|
||||||
|
|
||||||
|
### Keyword Yönetimi
|
||||||
|
|
||||||
|
Keyword'ler `@extend` ile tanımlanır — `identifier` token'ından türetilir ama **her zaman** keyword olarak parse edilir. dexpr'de keyword'ler reserved'dır (`if`, `then`, `else`, `end`, `in`, `true`, `false`).
|
||||||
|
|
||||||
|
### Error Recovery
|
||||||
|
|
||||||
|
Lezer GLR parser kullanır. Bozuk/yarım kod yazılırken:
|
||||||
|
- Parse edilebilen kısımlar doğru tree node'ları üretir
|
||||||
|
- Hatalı kısımlar `⚠` (error) node'ları ile sarılır
|
||||||
|
- Editör yarım kodda bile syntax highlighting ve autocomplete sunabilir
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Syntax Highlighting
|
||||||
|
|
||||||
|
**Dosya:** `src/language.ts` (tag eşleştirme) + `src/highlight.ts` (renk teması)
|
||||||
|
|
||||||
|
### Token → Tag Eşleştirmesi
|
||||||
|
|
||||||
|
| Token | Lezer Tag | Varsayılan Renk |
|
||||||
|
|-------|-----------|-----------------|
|
||||||
|
| `if`, `then`, `else`, `end`, `in`, `elseIf` | `keyword` | `#7c3aed` (mor) |
|
||||||
|
| `true`, `false` | `bool` | `#d97706` (turuncu) |
|
||||||
|
| `"string"`, `'string'` | `string` | `#059669` (yeşil) |
|
||||||
|
| `42`, `3.14` | `number` | `#2563eb` (mavi) |
|
||||||
|
| `// comment`, `/* comment */` | `lineComment` / `blockComment` | `#9ca3af` (gri, italic) |
|
||||||
|
| `+`, `-`, `*`, `/`, `%`, `!`, `\|\|`, `&&` | `operator` | `#dc2626` (kırmızı) |
|
||||||
|
| `==`, `!=`, `<`, `<=`, `>`, `>=`, `=`, `**` | `compareOperator` | `#dc2626` (kırmızı) |
|
||||||
|
| `myVar` | `variableName` | `#1f2937` (koyu) |
|
||||||
|
| `.method` | `propertyName` | `#0891b2` (cyan) |
|
||||||
|
| `functionName()` | `function(variableName)` | `#9333ea` (mor) |
|
||||||
|
|
||||||
|
Host uygulama `highlighting: false` vererek varsayılan temayı devre dışı bırakıp kendi temasını kullanabilir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Autocomplete
|
||||||
|
|
||||||
|
**Dosya:** `src/completions.ts`
|
||||||
|
|
||||||
|
### Veri Kaynağı
|
||||||
|
|
||||||
|
Autocomplete verileri `DexprLanguageInfo` arayüzü ile sağlanır. Bu veri Rust tarafında `LanguageInfo::to_json()` ile üretilir. Detaylar: [Language Info Modülü](language_info.md)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface DexprLanguageInfo {
|
||||||
|
functions: FunctionInfo[];
|
||||||
|
methods: Partial<Record<DexprType, MethodInfo[]>>;
|
||||||
|
variables?: VariableInfo[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tip Çıkarımı (Type Inference)
|
||||||
|
|
||||||
|
Completions modülü Lezer syntax tree'sini kullanarak değişken tiplerini çıkarır:
|
||||||
|
|
||||||
|
1. **Config'den gelen tipler:** `variables` dizisindeki her değişkenin tipi bilinir
|
||||||
|
2. **Assignment analizi:** `x = "hello"` → `x: String`, `y = 42` → `y: Number`
|
||||||
|
3. **Method dönüş tipi:** `z = name.split(",")` → `z: StringList` (`split` dönüş tipi bilinir)
|
||||||
|
4. **Binary expression:** `a = x + y` → string varsa `String`, number varsa `Number`
|
||||||
|
|
||||||
|
Bu analiz her autocomplete tetiklendiğinde Lezer tree üzerinde yapılır. Bozuk kodda bile parse edilmiş assignment'lar doğru tip bilgisi verir.
|
||||||
|
|
||||||
|
### Tetikleme Kuralları
|
||||||
|
|
||||||
|
| Durum | Davranış |
|
||||||
|
|-------|----------|
|
||||||
|
| `identifier` yazılırken | Keyword, fonksiyon, değişken önerileri |
|
||||||
|
| `.` yazıldığında | Dot öncesi ifadenin tipine göre metod önerileri |
|
||||||
|
| `.` + tip bilinmiyor | Tüm metodlar (fallback) |
|
||||||
|
| `.` + `Number` tipi | Öneri yok (ondalık yazımıyla karışmaz) |
|
||||||
|
| String / comment içinde | Öneri yok |
|
||||||
|
| Ctrl+Space | Explicit tetikleme |
|
||||||
|
|
||||||
|
### Metod Önerileri (tipe göre)
|
||||||
|
|
||||||
|
| Dot Öncesi | Gösterilen Metodlar |
|
||||||
|
|------------|---------------------|
|
||||||
|
| `"hello".` | String metodları |
|
||||||
|
| `category.` (config'de `String`) | String metodları |
|
||||||
|
| `x.` (assignment'tan `String` çıkarıldı) | String metodları |
|
||||||
|
| `items.` (config'de `StringList`) | StringList metodları |
|
||||||
|
| `scores.` (config'de `NumberList`) | NumberList metodları |
|
||||||
|
| `obj.` (config'de `Object`) | Object metodları |
|
||||||
|
| `result.` (tip bilinmiyor) | Tüm metodlar |
|
||||||
|
| `42.` | Öneri yok |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kurulum ve Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd editor
|
||||||
|
|
||||||
|
# Bağımlılıkları kur
|
||||||
|
bun install
|
||||||
|
|
||||||
|
# Lezer parser'ı grammar'dan üret
|
||||||
|
npx lezer-generator src/dexpr.grammar -o src/parser.js
|
||||||
|
|
||||||
|
# Kütüphaneyi build et
|
||||||
|
bun run build # → dist/index.js, dist/index.cjs, dist/index.d.ts
|
||||||
|
|
||||||
|
# Demo'yu build et (test için)
|
||||||
|
bun run demo # → dist/demo.global.js
|
||||||
|
|
||||||
|
# Demo'yu çalıştır
|
||||||
|
bunx serve . -p 3456 # → http://localhost:3456/demo.html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Grammar Değişikliği Yapıldığında
|
||||||
|
|
||||||
|
1. `src/dexpr.grammar` dosyasını düzenle
|
||||||
|
2. `npx lezer-generator src/dexpr.grammar -o src/parser.js` çalıştır
|
||||||
|
3. `bun run build` ile yeniden derle
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Host Uygulama Entegrasyonu
|
||||||
|
|
||||||
|
### 1. Rust Tarafı: Metadata Üretimi
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dexpr::language_info::LanguageInfo;
|
||||||
|
|
||||||
|
let mut info = LanguageInfo::builtin();
|
||||||
|
|
||||||
|
// VM'de register edilen her fonksiyon için:
|
||||||
|
info.add_function("getRate", "(code: String) -> Number", Some("Kur bilgisi"));
|
||||||
|
|
||||||
|
// VM'de register edilen her metod için:
|
||||||
|
info.add_method("String", "toTitleCase", "() -> String", None);
|
||||||
|
|
||||||
|
// VM'de set_global ile verilen her değişken için:
|
||||||
|
info.add_variable("price", "Number", None);
|
||||||
|
info.add_variable("category", "String", None);
|
||||||
|
|
||||||
|
let json = info.to_json();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Frontend Tarafı: Editör Oluşturma
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { EditorView, basicSetup } from "codemirror";
|
||||||
|
import { EditorState } from "@codemirror/state";
|
||||||
|
import { dexpr } from "codemirror-lang-dexpr";
|
||||||
|
|
||||||
|
// Rust'tan gelen JSON
|
||||||
|
const languageInfo = JSON.parse(jsonFromRust);
|
||||||
|
|
||||||
|
new EditorView({
|
||||||
|
state: EditorState.create({
|
||||||
|
doc: "",
|
||||||
|
extensions: [basicSetup, dexpr(languageInfo)],
|
||||||
|
}),
|
||||||
|
parent: document.getElementById("editor")!,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Dinamik Güncelleme
|
||||||
|
|
||||||
|
Eğer host uygulama çalışma sırasında yeni fonksiyon/değişken eklerse, editörü yeni `languageInfo` ile yeniden oluşturmak gerekir. CodeMirror'un `EditorView.dispatch` ile extension'ları güncellemek mümkündür ama en basit yol editörü yeniden oluşturmaktır.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Export'lar
|
||||||
|
|
||||||
|
### Ana Export
|
||||||
|
|
||||||
|
| Export | Tip | Açıklama |
|
||||||
|
|--------|-----|----------|
|
||||||
|
| `dexpr(config)` | `Extension` | All-in-one: language + autocomplete + highlighting |
|
||||||
|
|
||||||
|
### Granüler Export'lar
|
||||||
|
|
||||||
|
| Export | Açıklama |
|
||||||
|
|--------|----------|
|
||||||
|
| `dexprLanguage` | Sadece `LRLanguage` tanımı |
|
||||||
|
| `dexprCompletion(info)` | Sadece autocomplete extension'ı |
|
||||||
|
| `dexprHighlighting()` | Sadece varsayılan renk teması |
|
||||||
|
| `dexprHighlightStyle` | `HighlightStyle` nesnesi (özelleştirme için) |
|
||||||
|
| `KEYWORDS` | Keyword completion listesi |
|
||||||
|
|
||||||
|
### Tip Export'ları
|
||||||
|
|
||||||
|
| Tip | Açıklama |
|
||||||
|
|-----|----------|
|
||||||
|
| `DexprLanguageInfo` | Metadata arayüzü (JSON yapısı) |
|
||||||
|
| `DexprType` | `"String" \| "Number" \| "Boolean" \| "NumberList" \| "StringList" \| "Object"` |
|
||||||
|
| `FunctionInfo` | Fonksiyon metadata'sı |
|
||||||
|
| `MethodInfo` | Metod metadata'sı |
|
||||||
|
| `VariableInfo` | Değişken metadata'sı |
|
||||||
294
docs/embedding.md
Normal file
294
docs/embedding.md
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
# dexpr Embedding Guide
|
||||||
|
|
||||||
|
dexpr'i başka projelere embed etmenin iki yolu var:
|
||||||
|
|
||||||
|
1. **Rust backend + Web frontend** — Rust tarafında çalıştırma, frontend'de editör
|
||||||
|
2. **Tamamen tarayıcıda (WASM)** — Hem çalıştırma hem editör tarayıcıda
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Yol 1: Rust Backend + Web Frontend
|
||||||
|
|
||||||
|
Tipik senaryo: kullanıcı editörde formül yazar, backend derler ve çalıştırır.
|
||||||
|
|
||||||
|
### Rust tarafı
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# Cargo.toml
|
||||||
|
[dependencies]
|
||||||
|
dexpr = { path = "../dexpr" } # veya git/crates.io
|
||||||
|
rust_decimal_macros = "1.40"
|
||||||
|
indexmap = "2"
|
||||||
|
smol_str = "0.3"
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dexpr::{ast::value::Value, compiler::Compiler, vm::VM, language_info::LanguageInfo};
|
||||||
|
|
||||||
|
// ── 1. Verileri hazırla ──
|
||||||
|
// JSON'dan (API, DB, config, vb.)
|
||||||
|
let customer = Value::from_json(r#"{
|
||||||
|
"name": "Alice",
|
||||||
|
"email": "alice@test.com",
|
||||||
|
"age": 30,
|
||||||
|
"active": true,
|
||||||
|
"tags": ["premium", "tr"]
|
||||||
|
}"#).unwrap();
|
||||||
|
|
||||||
|
let order = Value::from_json(r#"{
|
||||||
|
"amount": 1500,
|
||||||
|
"currency": "TRY",
|
||||||
|
"items": ["laptop", "mouse"]
|
||||||
|
}"#).unwrap();
|
||||||
|
|
||||||
|
// ── 2. Editör metadata'sını üret (sayfa yüklenirken, 1 kez) ──
|
||||||
|
let mut info = LanguageInfo::builtin();
|
||||||
|
|
||||||
|
// Değişkenler — tip ve field bilgisi Value'dan otomatik çıkar
|
||||||
|
info.add_value("customer", &customer, Some("Müşteri bilgisi".into()));
|
||||||
|
info.add_value("order", &order, Some("Sipariş bilgisi".into()));
|
||||||
|
info.add_value("discount", &Value::Number(rust_decimal_macros::dec!(10)), None);
|
||||||
|
|
||||||
|
// Host fonksiyonları
|
||||||
|
info.add_function("getRate", "(code: String) -> Number", Some("Döviz kuru"));
|
||||||
|
info.add_function("fetchPrice", "(sku: String) -> Number", None);
|
||||||
|
|
||||||
|
let editor_json = info.to_json();
|
||||||
|
// → bu JSON'ı bir endpoint ile frontend'e gönder
|
||||||
|
|
||||||
|
// ── 3. Kullanıcının yazdığı kodu çalıştır ──
|
||||||
|
fn execute_dexpr(
|
||||||
|
source: &str,
|
||||||
|
globals: &[(&str, Value)],
|
||||||
|
) -> Result<Value, String> {
|
||||||
|
let mut compiler = Compiler::new();
|
||||||
|
let (bytecode, debug_info) = compiler
|
||||||
|
.compile_from_source(source)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let mut vm = VM::new(&bytecode);
|
||||||
|
vm.set_debug_info(&debug_info);
|
||||||
|
|
||||||
|
for (name, value) in globals {
|
||||||
|
vm.set_global(name, value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Host fonksiyonları kaydet
|
||||||
|
vm.register_function("getRate", |args| {
|
||||||
|
// args[0]: currency code
|
||||||
|
Ok(Value::Number(rust_decimal_macros::dec!(34.5)))
|
||||||
|
});
|
||||||
|
|
||||||
|
vm.execute().map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kullanıcının formülü:
|
||||||
|
let result = execute_dexpr(
|
||||||
|
"order.amount * (1 - discount / 100)",
|
||||||
|
&[
|
||||||
|
("customer", customer),
|
||||||
|
("order", order),
|
||||||
|
("discount", Value::Number(rust_decimal_macros::dec!(10))),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
// → Ok(Number(1350))
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend tarafı
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install codemirror codemirror-lang-dexpr
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { EditorView, basicSetup } from "codemirror";
|
||||||
|
import { EditorState } from "@codemirror/state";
|
||||||
|
import { dexpr } from "codemirror-lang-dexpr";
|
||||||
|
|
||||||
|
// ── 1. Backend'den metadata al ──
|
||||||
|
const langInfo = await fetch("/api/editor-metadata").then(r => r.json());
|
||||||
|
|
||||||
|
// ── 2. Editörü oluştur ──
|
||||||
|
const editor = new EditorView({
|
||||||
|
state: EditorState.create({
|
||||||
|
doc: "",
|
||||||
|
extensions: [basicSetup, dexpr(langInfo)],
|
||||||
|
}),
|
||||||
|
parent: document.getElementById("editor")!,
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── 3. Çalıştır ──
|
||||||
|
async function run() {
|
||||||
|
const code = editor.state.doc.toString();
|
||||||
|
const res = await fetch("/api/execute", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ code }),
|
||||||
|
});
|
||||||
|
const { result, error } = await res.json();
|
||||||
|
document.getElementById("output")!.textContent =
|
||||||
|
error ?? JSON.stringify(result);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Akış
|
||||||
|
|
||||||
|
```
|
||||||
|
Frontend Backend (Rust)
|
||||||
|
─────── ──────────────
|
||||||
|
GET /editor-metadata ──────────► LanguageInfo::to_json()
|
||||||
|
◄─────────────────────────────── JSON (functions, methods, variables+fields)
|
||||||
|
|
||||||
|
dexpr(langInfo)
|
||||||
|
customer. → [name, email, age, ...]
|
||||||
|
customer.name. → [upper, lower, trim, ...]
|
||||||
|
|
||||||
|
POST /execute { code } ────────► Compiler::compile_from_source()
|
||||||
|
VM::new() + set_global() + execute()
|
||||||
|
◄─────────────────────────────── { result: 1350 }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Yol 2: Tamamen Tarayıcıda (WASM)
|
||||||
|
|
||||||
|
Backend'e gerek yok. Parser, compiler, VM hepsi tarayıcıda çalışır.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd wasm
|
||||||
|
wasm-pack build --target web --release
|
||||||
|
# → wasm/pkg/ altında JS + WASM + TypeScript types üretilir
|
||||||
|
```
|
||||||
|
|
||||||
|
`pkg/` içeriği:
|
||||||
|
- `dexpr_wasm_bg.wasm` (~370KB) — WASM binary
|
||||||
|
- `dexpr_wasm.js` — JS glue code (auto-init)
|
||||||
|
- `dexpr_wasm.d.ts` — TypeScript type definitions
|
||||||
|
|
||||||
|
### Kullanım
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="editor"></div>
|
||||||
|
<button onclick="run()">Çalıştır</button>
|
||||||
|
<pre id="output"></pre>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import init, { DexprEngine } from "./pkg/dexpr_wasm.js";
|
||||||
|
import { EditorView, basicSetup } from "codemirror";
|
||||||
|
import { EditorState } from "@codemirror/state";
|
||||||
|
import { dexpr } from "codemirror-lang-dexpr";
|
||||||
|
|
||||||
|
// ── 1. WASM'ı başlat ──
|
||||||
|
await init();
|
||||||
|
const engine = new DexprEngine();
|
||||||
|
|
||||||
|
// ── 2. Global'leri JSON string olarak ver ──
|
||||||
|
engine.setGlobal("customer", JSON.stringify({
|
||||||
|
name: "Alice",
|
||||||
|
email: "alice@test.com",
|
||||||
|
age: 30,
|
||||||
|
active: true,
|
||||||
|
tags: ["premium", "tr"],
|
||||||
|
}));
|
||||||
|
|
||||||
|
engine.setGlobal("order", JSON.stringify({
|
||||||
|
amount: 1500,
|
||||||
|
currency: "TRY",
|
||||||
|
items: ["laptop", "mouse"],
|
||||||
|
}));
|
||||||
|
|
||||||
|
engine.setGlobal("discount", "10");
|
||||||
|
|
||||||
|
// ── 3. Host fonksiyon kaydet ──
|
||||||
|
engine.registerFunction("getRate", (argsJson) => {
|
||||||
|
const args = JSON.parse(argsJson);
|
||||||
|
const code = args[0]; // currency code string
|
||||||
|
const rates = { USD: 34.5, EUR: 37.2 };
|
||||||
|
return JSON.stringify(rates[code] ?? 0);
|
||||||
|
});
|
||||||
|
engine.addFunctionInfo("getRate", "(code: String) -> Number", "Döviz kuru");
|
||||||
|
|
||||||
|
// ── 4. Editör metadata'sını engine'den al ──
|
||||||
|
// setGlobal çağrıları otomatik olarak field tiplerini algılar
|
||||||
|
const langInfo = JSON.parse(engine.languageInfo());
|
||||||
|
|
||||||
|
// ── 5. CodeMirror editörünü oluştur ──
|
||||||
|
const editor = new EditorView({
|
||||||
|
state: EditorState.create({
|
||||||
|
doc: `// customer ve order WASM engine'e JSON olarak verildi
|
||||||
|
name = customer.name.upper()
|
||||||
|
total = order.amount * (1 - discount / 100)
|
||||||
|
log(name, total)
|
||||||
|
total`,
|
||||||
|
extensions: [basicSetup, dexpr(langInfo)],
|
||||||
|
}),
|
||||||
|
parent: document.getElementById("editor"),
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── 6. Çalıştır butonu ──
|
||||||
|
window.run = function() {
|
||||||
|
try {
|
||||||
|
const code = editor.state.doc.toString();
|
||||||
|
const resultJson = engine.execute(code);
|
||||||
|
const result = JSON.parse(resultJson);
|
||||||
|
document.getElementById("output").textContent = JSON.stringify(result, null, 2);
|
||||||
|
|
||||||
|
// Global'ler güncellendi mi kontrol et
|
||||||
|
const customer = JSON.parse(engine.getGlobal("customer"));
|
||||||
|
console.log("customer after:", customer);
|
||||||
|
} catch (e) {
|
||||||
|
document.getElementById("output").textContent = "Error: " + e.message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Referansı
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class DexprEngine {
|
||||||
|
constructor()
|
||||||
|
|
||||||
|
// Global değişken: JSON string olarak ver/al
|
||||||
|
setGlobal(name: string, json: string): void
|
||||||
|
getGlobal(name: string): string | undefined
|
||||||
|
|
||||||
|
// Çalıştır: kaynak kodu → sonuç JSON string
|
||||||
|
execute(source: string): string
|
||||||
|
|
||||||
|
// Host fonksiyonu kaydet (args ve return JSON string olarak)
|
||||||
|
registerFunction(name: string, fn: (argsJson: string) => string): void
|
||||||
|
|
||||||
|
// Editör metadata (otomatik güncellenir her setGlobal'de)
|
||||||
|
languageInfo(): string
|
||||||
|
|
||||||
|
// Editör autocomplete için fonksiyon bilgisi
|
||||||
|
addFunctionInfo(name: string, signature: string, doc?: string): void
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dikkat Edilmesi Gerekenler
|
||||||
|
|
||||||
|
- **JSON string convention**: `setGlobal` ve `execute` JSON *string* alır/verir — `JSON.stringify()` ve `JSON.parse()` kullan
|
||||||
|
- **Global sync**: `execute()` sonrası property assignment'lar (`customer.city = "Ankara"`) global'lere yansır — `getGlobal()` ile güncel halini al
|
||||||
|
- **Host fonksiyonlar**: Args ve return JSON string — `(argsJson: string) => string`
|
||||||
|
- **Editör metadata**: `setGlobal()` her çağrıldığında `languageInfo()` otomatik güncellenir (field tipleri Value'dan çıkarılır)
|
||||||
|
- **WASM boyutu**: Release build ~370KB (gzip ile ~120KB)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Karşılaştırma
|
||||||
|
|
||||||
|
| | Rust Backend | WASM |
|
||||||
|
|---|---|---|
|
||||||
|
| **Çalıştırma** | Server'da | Tarayıcıda |
|
||||||
|
| **Performans** | Native hız | ~2-3x native |
|
||||||
|
| **Güvenlik** | Server-side validation | Client-side (güvenilir ortam) |
|
||||||
|
| **Latency** | Network roundtrip | Anında |
|
||||||
|
| **Deployment** | Backend deploy | Static dosya |
|
||||||
|
| **Host fonksiyonlar** | Rust closure'ları | JS callback (JSON bridge) |
|
||||||
|
| **DB/API erişimi** | Doğrudan | Fetch ile |
|
||||||
|
|
||||||
|
**Öneri**: Güvenlik kritikse (fiyat hesaplama, kurallar) → Rust backend. İnteraktif preview/sandbox → WASM.
|
||||||
156
docs/language_info.md
Normal file
156
docs/language_info.md
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
# Language Info Modülü
|
||||||
|
|
||||||
|
**Konum:** `src/language_info.rs`
|
||||||
|
|
||||||
|
Editör entegrasyonu için dil metadata'sı üretir. Built-in fonksiyonlar, tipe göre metodlar ve host-kayıtlı genişletmeleri JSON formatında dışa aktarır. Frontend editör kütüphanesi (`codemirror-lang-dexpr`) bu JSON'u alarak tip-bazlı autocomplete sağlar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Yapılar
|
||||||
|
|
||||||
|
### FunctionInfo
|
||||||
|
|
||||||
|
| Alan | Tip | Açıklama |
|
||||||
|
|------|-----|----------|
|
||||||
|
| `name` | `&'static str` | Fonksiyon adı |
|
||||||
|
| `signature` | `&'static str` | İmza (örn: `"(min, max) -> Number"`) |
|
||||||
|
| `doc` | `Option<&'static str>` | Opsiyonel açıklama |
|
||||||
|
|
||||||
|
### MethodInfo
|
||||||
|
|
||||||
|
| Alan | Tip | Açıklama |
|
||||||
|
|------|-----|----------|
|
||||||
|
| `name` | `&'static str` | Metod adı |
|
||||||
|
| `signature` | `&'static str` | İmza (örn: `"() -> String"`) |
|
||||||
|
| `doc` | `Option<&'static str>` | Opsiyonel açıklama |
|
||||||
|
|
||||||
|
### VariableInfo
|
||||||
|
|
||||||
|
| Alan | Tip | Açıklama |
|
||||||
|
|------|-----|----------|
|
||||||
|
| `name` | `String` | Değişken adı |
|
||||||
|
| `type_name` | `String` | Tip adı: `String`, `Number`, `Boolean`, `NumberList`, `StringList`, `Object` |
|
||||||
|
| `doc` | `Option<String>` | Opsiyonel açıklama |
|
||||||
|
|
||||||
|
### LanguageInfo
|
||||||
|
|
||||||
|
Tüm metadata'yı toplayan ana yapı.
|
||||||
|
|
||||||
|
| Alan | Tip | Açıklama |
|
||||||
|
|------|-----|----------|
|
||||||
|
| `functions` | `Vec<FunctionInfo>` | Fonksiyon listesi |
|
||||||
|
| `methods` | `Vec<(&'static str, Vec<MethodInfo>)>` | Tipe göre metod listesi |
|
||||||
|
| `variables` | `Vec<VariableInfo>` | Değişken listesi |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Metodlar
|
||||||
|
|
||||||
|
### `LanguageInfo::builtin() -> Self`
|
||||||
|
|
||||||
|
Tüm built-in fonksiyon ve metodları içeren yeni bir `LanguageInfo` oluşturur.
|
||||||
|
|
||||||
|
**Built-in fonksiyonlar:** `log`, `rand`
|
||||||
|
|
||||||
|
**Built-in metodlar (tipe göre):**
|
||||||
|
|
||||||
|
| Tip | Metodlar |
|
||||||
|
|-----|----------|
|
||||||
|
| `String` | `upper`, `lower`, `trim`, `trimStart`, `trimEnd`, `split`, `replace`, `contains`, `startsWith`, `endsWith`, `length`, `charAt`, `substring` |
|
||||||
|
| `Number` | *(yok)* |
|
||||||
|
| `Boolean` | *(yok)* |
|
||||||
|
| `NumberList` | `length`, `len`, `isEmpty`, `first`, `last`, `get`, `contains`, `indexOf`, `slice`, `reverse`, `sort`, `sum`, `avg`, `min`, `max` |
|
||||||
|
| `StringList` | `length`, `len`, `isEmpty`, `first`, `last`, `get`, `contains`, `indexOf`, `slice`, `reverse`, `sort`, `join` |
|
||||||
|
| `Object` | `keys`, `values`, `length`, `len`, `contains`, `get` |
|
||||||
|
|
||||||
|
### `add_function(name, signature, doc)`
|
||||||
|
|
||||||
|
Host-kayıtlı fonksiyon ekler (VM'deki `register_function` ile eşleşir).
|
||||||
|
|
||||||
|
### `add_method(type_name, name, signature, doc)`
|
||||||
|
|
||||||
|
Host-kayıtlı metod ekler (VM'deki `register_method` ile eşleşir). Belirtilen tipe ait metod listesine eklenir.
|
||||||
|
|
||||||
|
### `add_variable(name, type_name, doc)`
|
||||||
|
|
||||||
|
External değişken ekler (VM'deki `set_global` ile eşleşir). Editörde autocomplete ve tip-bazlı metod önerileri için kullanılır.
|
||||||
|
|
||||||
|
### `to_json() -> String`
|
||||||
|
|
||||||
|
Tüm metadata'yı JSON formatında serileştirir. Frontend editör kütüphanesine gönderilecek çıktıyı üretir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## JSON Formatı
|
||||||
|
|
||||||
|
`to_json()` çıktısı:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"functions": [
|
||||||
|
{"name": "log", "signature": "(...args) -> null", "doc": "Print values to output"},
|
||||||
|
{"name": "getRate", "signature": "(code: String) -> Number", "doc": "Get exchange rate"}
|
||||||
|
],
|
||||||
|
"methods": {
|
||||||
|
"String": [
|
||||||
|
{"name": "upper", "signature": "() -> String"},
|
||||||
|
{"name": "toTitleCase", "signature": "() -> String", "doc": "Custom host method"}
|
||||||
|
],
|
||||||
|
"Number": [],
|
||||||
|
"NumberList": [
|
||||||
|
{"name": "sum", "signature": "() -> Number"}
|
||||||
|
],
|
||||||
|
"StringList": [
|
||||||
|
{"name": "join", "signature": "(delim?: String) -> String"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{"name": "price", "type": "Number"},
|
||||||
|
{"name": "category", "type": "String", "doc": "Product category"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kullanım Örneği
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dexpr::language_info::LanguageInfo;
|
||||||
|
|
||||||
|
// 1. Built-in metadata oluştur
|
||||||
|
let mut info = LanguageInfo::builtin();
|
||||||
|
|
||||||
|
// 2. Host fonksiyonları ekle (register_function ile eşleşmeli)
|
||||||
|
info.add_function("getRate", "(code: String) -> Number", Some("Get exchange rate"));
|
||||||
|
info.add_function("fetchPrice", "(sku: String) -> Number", None);
|
||||||
|
|
||||||
|
// 3. Host metodları ekle (register_method ile eşleşmeli)
|
||||||
|
info.add_method("String", "toTitleCase", "() -> String", None);
|
||||||
|
|
||||||
|
// 4. External değişkenleri ekle (set_global ile eşleşmeli)
|
||||||
|
info.add_variable("price", "Number", None);
|
||||||
|
info.add_variable("category", "String", Some("Ürün kategorisi".to_string()));
|
||||||
|
info.add_variable("items", "StringList", None);
|
||||||
|
|
||||||
|
// 5. JSON üret ve frontend'e gönder
|
||||||
|
let json = info.to_json();
|
||||||
|
// json -> HTTP response, WebSocket message, vb.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Frontend Entegrasyonu
|
||||||
|
|
||||||
|
Üretilen JSON doğrudan `codemirror-lang-dexpr` kütüphanesine verilir:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { dexpr } from "codemirror-lang-dexpr";
|
||||||
|
|
||||||
|
// Rust'tan gelen JSON parse edilir
|
||||||
|
const languageInfo = JSON.parse(jsonFromRust);
|
||||||
|
|
||||||
|
const extensions = [basicSetup, dexpr(languageInfo)];
|
||||||
|
```
|
||||||
|
|
||||||
|
Detaylar için: [Editor Modülü](editor.md)
|
||||||
95
docs/opcodes.md
Normal file
95
docs/opcodes.md
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# Opcodes Modülü
|
||||||
|
|
||||||
|
**Konum:** `src/opcodes.rs`
|
||||||
|
|
||||||
|
Bytecode komut setini (instruction set) tanımlar. Her opcode bir `u8` değerine karşılık gelir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OpCodeByte Enum
|
||||||
|
|
||||||
|
### Register Operasyonları
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `LoadConst` | `0x10` | Sabit değeri register'a yükle |
|
||||||
|
| `Move` | `0x11` | Register'dan register'a kopyala |
|
||||||
|
|
||||||
|
### Bellek Operasyonları
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `LoadLocal` | `0x20` | Yerel değişkeni register'a yükle (ayrılmış) |
|
||||||
|
| `StoreLocal` | `0x21` | Register'ı yerel değişkene kaydet (ayrılmış) |
|
||||||
|
| `LoadGlobal` | `0x22` | Global değişkeni register'a yükle |
|
||||||
|
| `StoreGlobal` | `0x23` | Register'ı global değişkene kaydet |
|
||||||
|
|
||||||
|
> **Not:** `LoadLocal`/`StoreLocal` opcode'ları tanımlıdır ancak şu an compiler tarafından emit edilmez. Tüm değişkenler global scope'tadır.
|
||||||
|
|
||||||
|
### Aritmetik
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `Add` | `0x30` | Toplama |
|
||||||
|
| `Sub` | `0x31` | Çıkarma |
|
||||||
|
| `Mul` | `0x32` | Çarpma |
|
||||||
|
| `Div` | `0x33` | Bölme |
|
||||||
|
| `Neg` | `0x34` | Negatif (tekli) |
|
||||||
|
| `Mod` | `0x35` | Mod alma |
|
||||||
|
| `Pow` | `0x36` | Üs alma |
|
||||||
|
|
||||||
|
### Karşılaştırma
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `Lt` | `0x40` | Küçüktür |
|
||||||
|
| `Lte` | `0x41` | Küçük eşit |
|
||||||
|
| `Gt` | `0x42` | Büyüktür |
|
||||||
|
| `Gte` | `0x43` | Büyük eşit |
|
||||||
|
| `Eq` | `0x44` | Eşit |
|
||||||
|
| `Neq` | `0x45` | Eşit değil |
|
||||||
|
|
||||||
|
### Boolean Mantık
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `And` | `0x50` | Mantıksal VE |
|
||||||
|
| `Or` | `0x51` | Mantıksal VEYA |
|
||||||
|
| `Not` | `0x52` | Mantıksal DEĞİL |
|
||||||
|
|
||||||
|
### Kontrol Akışı
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `Jump` | `0x60` | Koşulsuz atlama |
|
||||||
|
| `JumpIfFalse` | `0x61` | Register false ise atla |
|
||||||
|
|
||||||
|
### Üyelik Testi
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `Contains` | `0x53` | Değer listede/string'de var mı kontrolü (`in` operatörü) |
|
||||||
|
|
||||||
|
### Özel Operasyonlar
|
||||||
|
|
||||||
|
| Opcode | Değer | Açıklama |
|
||||||
|
|--------|-------|----------|
|
||||||
|
| `Concat` | `0x80` | String birleştirme |
|
||||||
|
| `MethodCall` | `0x90` | Metod çağrısı |
|
||||||
|
| `GetProperty` | `0x91` | Nesne özelliği oku (dest, obj_reg, property_name_string) |
|
||||||
|
| `SetProperty` | `0x92` | Nesne özelliği yaz (obj_reg, property_name_string, val_reg) |
|
||||||
|
| `Log` | `0xA0` | Değer yazdır (built-in) |
|
||||||
|
| `CallExternal` | `0xA1` | Harici (host) fonksiyon çağrısı |
|
||||||
|
| `SetResult` | `0xB0` | İfade sonucunu kaydet (return value için) |
|
||||||
|
| `End` | `0xFF` | Program sonu |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hızlı Lookup Tablosu
|
||||||
|
|
||||||
|
`LOOKUP[256]` statik dizisi, O(1) karmaşıklıkta byte-to-opcode dönüşümü sağlar. `from_byte(u8)` metodu bu tabloyu kullanır.
|
||||||
|
|
||||||
|
**Metodlar:**
|
||||||
|
- `to_byte() -> u8` — Opcode'u byte'a dönüştür
|
||||||
|
- `from_byte(u8) -> Option<OpCodeByte>` — Byte'ı opcode'a dönüştür (lookup tablosu ile)
|
||||||
|
- `name() -> &str` — İnsan okunabilir opcode adı
|
||||||
115
docs/parser.md
Normal file
115
docs/parser.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# Parser Modülü
|
||||||
|
|
||||||
|
**Konum:** `src/parser/`
|
||||||
|
|
||||||
|
Parser, kaynak kodu AST'ye dönüştürür. PEG (Parsing Expression Grammar) tabanlıdır ve `peg` crate'ini kullanır.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Giriş Noktaları
|
||||||
|
|
||||||
|
**Dosya:** `src/parser/mod.rs`
|
||||||
|
|
||||||
|
| Fonksiyon | Dönüş | Açıklama |
|
||||||
|
|-----------|-------|----------|
|
||||||
|
| `program(source)` | `Vec<Stmt>` | Tam programı parse eder |
|
||||||
|
| `program_with_spans(source)` | `Vec<(usize, Stmt)>` | Byte offset'leriyle birlikte parse eder |
|
||||||
|
|
||||||
|
### `offset_to_span(source, offset) -> Span`
|
||||||
|
Byte offset'ini 1-indexed satır ve sütuna dönüştürür. UTF-8 karakter sınırlarını doğru şekilde hesaplar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gramer Kuralları
|
||||||
|
|
||||||
|
**Dosya:** `src/parser/grammar.rs`
|
||||||
|
|
||||||
|
### Deyim (Statement) Ayrıştırma
|
||||||
|
|
||||||
|
| Kural | Ürettiği | Sözdizimi |
|
||||||
|
|-------|----------|-----------|
|
||||||
|
| `statement()` | `Stmt` | Herhangi bir geçerli deyim |
|
||||||
|
| `assignment()` | `Stmt::Assignment` | `x = expr` veya `x += expr` |
|
||||||
|
| `property_assignment()` | `Stmt::PropertyAssignment` | `a.b.c = expr` |
|
||||||
|
| `expr_stmt()` | `Stmt::ExprStmt` | Bağımsız ifade |
|
||||||
|
| `if_stmt()` | `Stmt::If` | `if cond then ... [else ...] end` |
|
||||||
|
|
||||||
|
**Bileşik atamalar:** `+=`, `-=`, `*=`, `/=`, `%=` operatörleri desugar edilir:
|
||||||
|
- `x += e` → `x = x + e`
|
||||||
|
|
||||||
|
**Özellik ataması:** `identifier ("." identifier)+ "=" expression` kalıbı ile nesne özelliklerine atama yapılır (örn: `a.b.c = 42`).
|
||||||
|
|
||||||
|
**Else zincirleri:** `else if` yapısı desteklenir ve rekürsif olarak parse edilir.
|
||||||
|
|
||||||
|
### İfade (Expression) Ayrıştırma - Öncelik Sırası
|
||||||
|
|
||||||
|
En düşükten en yükseğe:
|
||||||
|
|
||||||
|
1. Method çağrıları, fonksiyon çağrıları
|
||||||
|
2. Mantıksal AND (`&&`)
|
||||||
|
3. Mantıksal OR (`||`)
|
||||||
|
4. Karşılaştırma (`==`, `!=`, `<`, `<=`, `>`, `>=`, `in`)
|
||||||
|
5. Toplama/Çıkarma (`+`, `-`)
|
||||||
|
6. Çarpma/Bölme/Mod (`*`, `/`, `%`)
|
||||||
|
7. Üs alma (`**`) - sağdan birleşimli (right-associative)
|
||||||
|
8. Tekli operatörler (`-`, `!`), atomik ifadeler
|
||||||
|
|
||||||
|
### Postfix Kuralı
|
||||||
|
|
||||||
|
`postfix()` kuralı, herhangi bir atom üzerinde `.property` (özellik erişimi) ve `.method(args)` (metod çağrısı) zincirlemesini sağlar. Atom parse edildikten sonra ardışık `.identifier` veya `.identifier(args)` kalıpları uygulanır:
|
||||||
|
|
||||||
|
- `obj.field` → `Expr::PropertyAccess(obj, "field")`
|
||||||
|
- `obj.method(args)` → `Expr::MethodCall(obj, "method", args)`
|
||||||
|
- `obj.a.b.method()` → zincirleme erişim ve çağrı
|
||||||
|
|
||||||
|
### Atomik İfadeler
|
||||||
|
|
||||||
|
`atom()` kuralı temel ifade birimlerini parse eder:
|
||||||
|
|
||||||
|
| Tür | Örnek | Ürettiği |
|
||||||
|
|-----|-------|----------|
|
||||||
|
| Tanımlayıcı | `myVar` | `Expr::Variable` |
|
||||||
|
| Sayı | `42`, `3.14` | `Expr::Value(Number)` |
|
||||||
|
| String | `"hello"`, `'world'` | `Expr::Value(String)` |
|
||||||
|
| Boolean | `true`, `false` | `Expr::Value(Boolean)` |
|
||||||
|
| Parantezli ifade | `(a + b)` | İç ifade |
|
||||||
|
| Tekli negatif | `-x` | `Expr::UnaryOp(Neg, x)` |
|
||||||
|
| Tekli NOT | `!flag` | `Expr::UnaryOp(Not, flag)` |
|
||||||
|
|
||||||
|
### Literal Ayrıştırma
|
||||||
|
|
||||||
|
- **Sayılar:** Ondalık kısım opsiyonel (`42`, `3.14`)
|
||||||
|
- **Stringler:** Çift veya tek tırnak, escape sequence destekli
|
||||||
|
- **Tanımlayıcılar:** Ayrılmış kelimelerle çakışmamalı
|
||||||
|
|
||||||
|
### Ayrılmış Kelimeler
|
||||||
|
|
||||||
|
`if`, `then`, `else`, `end`, `true`, `false`, `in`
|
||||||
|
|
||||||
|
### Boşluk ve Yorumlar
|
||||||
|
|
||||||
|
- Boşluklar: space, tab, newline
|
||||||
|
- Satır yorumu: `// ...`
|
||||||
|
- Blok yorumu: `/* ... */`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hata Yönetimi
|
||||||
|
|
||||||
|
Parser hataları `peg` crate'inden gelir ve beklenen token/kural bilgisi içerir. `program_with_spans()` kullanıldığında byte offset'leri `offset_to_span()` ile satır/sütun bilgisine dönüştürülebilir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kullanım Örneği
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use dexpr::parser;
|
||||||
|
|
||||||
|
let source = r#"
|
||||||
|
result = (3 + 4) * 2
|
||||||
|
log(result)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let ast = parser::program(source).expect("Parse error");
|
||||||
|
// ast: Vec<Stmt> - Assignment, ExprStmt
|
||||||
|
```
|
||||||
202
docs/vm.md
Normal file
202
docs/vm.md
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
# VM (Virtual Machine) Modülü
|
||||||
|
|
||||||
|
**Konum:** `src/vm/`
|
||||||
|
|
||||||
|
Register tabanlı sanal makine. Bytecode'u çalıştırır, 8 register ve global değişken deposu içerir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Alt Modüller
|
||||||
|
|
||||||
|
| Dosya | İçerik |
|
||||||
|
|-------|--------|
|
||||||
|
| `vm/mod.rs` | Modül export'ları |
|
||||||
|
| `vm/vm.rs` | Ana VM implementasyonu |
|
||||||
|
| `vm/error.rs` | Hata türleri (VMError) |
|
||||||
|
| `vm/debug_info.rs` | Bytecode offset → kaynak konum eşleştirme |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## VMError (Hata Türleri)
|
||||||
|
|
||||||
|
**Dosya:** `src/vm/error.rs`
|
||||||
|
|
||||||
|
| Hata | Açıklama |
|
||||||
|
|------|----------|
|
||||||
|
| `TypeMismatch { expected, got }` | Tip uyuşmazlığı |
|
||||||
|
| `UndefinedVariable(SmolStr)` | Tanımlanmamış değişken |
|
||||||
|
| `DivisionByZero` | Sıfıra bölme |
|
||||||
|
| `BytecodeError(String)` | Bozuk bytecode |
|
||||||
|
| `MethodNotFound { type_name, method }` | Metod bulunamadı |
|
||||||
|
| `RuntimeError(String)` | Genel çalışma zamanı hatası |
|
||||||
|
| `InvalidOperation { operation, left_type, right_type }` | Desteklenmeyen operasyon |
|
||||||
|
| `WithLocation { span, message }` | Kaynak konum bilgili hata |
|
||||||
|
|
||||||
|
`with_span(span)` metodu hatayı kaynak konum bilgisi ile sarar (çift sarmalamayı önler).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DebugInfo
|
||||||
|
|
||||||
|
**Dosya:** `src/vm/debug_info.rs`
|
||||||
|
|
||||||
|
Bytecode offset'lerini kaynak kod konumlarına (Span) eşleştirir. Run-length encoded yapıda: her girdi bir sonraki girdiye kadar geçerlidir.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct DebugInfo {
|
||||||
|
entries: Vec<(u32, Span)>, // sıralı (offset, span) çiftleri
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Metodlar:**
|
||||||
|
- `add_entry(offset, span)` — Eşleştirme ekle (artan offset sırasında)
|
||||||
|
- `get_span(offset) -> Option<Span>` — Binary search ile konum bul
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## VM Yapısı
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct VM<'a> {
|
||||||
|
// Bytecode durumu
|
||||||
|
bytecode: &'a [u8],
|
||||||
|
reader: BytecodeReader<'a>,
|
||||||
|
pc: usize,
|
||||||
|
|
||||||
|
// Hesaplama
|
||||||
|
registers: [Value; 8], // 8 register
|
||||||
|
|
||||||
|
// Değişkenler
|
||||||
|
globals: Map<SmolStr, Value, 64>, // Global kapsam (max 64 giriş)
|
||||||
|
|
||||||
|
// Kaynaklar
|
||||||
|
heap: Bump, // Bump allocator
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
debug_info: Option<DebugInfo>,
|
||||||
|
debug: bool, // Debug çıktısı (debug build'lerde)
|
||||||
|
opcode_counts: [usize; 256], // Profiling (debug build'lerde)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Başlatma ve API
|
||||||
|
|
||||||
|
| Metod | Açıklama |
|
||||||
|
|-------|----------|
|
||||||
|
| `new(bytecode)` | VM oluştur |
|
||||||
|
| `set_debug_info(debug_info)` | Kaynak konum eşleştirmesi sağla |
|
||||||
|
| `set_global(name, value)` | Global değişken ata |
|
||||||
|
| `get_global(name) -> Option<&Value>` | Global değişken oku |
|
||||||
|
| `register_function(name, fn)` | Harici (host) fonksiyon kaydet |
|
||||||
|
| `register_method(type_name, method_name, fn)` | Tipe özel harici metod kaydet |
|
||||||
|
| `reset()` | Durumu sıfırla, yeniden çalıştırmaya hazırla |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Çalıştırma Döngüsü
|
||||||
|
|
||||||
|
`execute() -> Result<Value, VMError>` (son expression'ın değerini döndürür):
|
||||||
|
|
||||||
|
1. VM durumunu sıfırla
|
||||||
|
2. Bytecode kaldığı sürece döngüde çalış:
|
||||||
|
- Opcode byte'ını oku
|
||||||
|
- İlgili handler'a yönlendir
|
||||||
|
- Hataları kaynak konum bilgisi ile sar
|
||||||
|
- Profiling verilerini güncelle (debug build)
|
||||||
|
- `End` opcode'unda dur
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Opcode Handler'ları
|
||||||
|
|
||||||
|
### Register ve Bellek
|
||||||
|
- **`handle_load_const()`** — Bytecode'dan değer oku, register'a koy
|
||||||
|
- **`handle_move()`** — Register → register kopyala
|
||||||
|
- **`handle_load_global()`** — Global map → register
|
||||||
|
- **`handle_store_global()`** — Register → global map
|
||||||
|
|
||||||
|
### Aritmetik
|
||||||
|
- **`binary_op(f, name)`** — Genel handler: iki operand register'ı oku, fonksiyonu uygula, sonucu kaydet
|
||||||
|
- Sıfıra bölme kontrolü yapılır
|
||||||
|
- **`handle_neg()`** — Sadece Number tipinde tekli negatif
|
||||||
|
|
||||||
|
### Karşılaştırma
|
||||||
|
- **`compare_op(f, name)`** — Decimal değerler üzerinde karşılaştırma, Boolean döndürür
|
||||||
|
|
||||||
|
### Boolean
|
||||||
|
- **`handle_and()`**, **`handle_or()`**, **`handle_not()`** — Boolean register'lar üzerinde mantık operasyonları
|
||||||
|
|
||||||
|
### Kontrol Akışı
|
||||||
|
- **`handle_jump()`** — 4-byte adres oku, reader pozisyonunu ayarla
|
||||||
|
- **`handle_jump_if_false()`** — Register `Boolean(false)` ise atla
|
||||||
|
|
||||||
|
### String, Nesne ve Metodlar
|
||||||
|
- **`handle_concat()`** — İki String register'ını birleştir
|
||||||
|
- **`handle_get_property()`** — Object register'ından alan oku, alan yoksa `Null` döndür
|
||||||
|
- **`handle_set_property()`** — Object register'ında alan değerini ayarla
|
||||||
|
- **`handle_method_call()`** — Nesne register'ı, metod adı, argümanlar
|
||||||
|
- **String metodları:** `upper`, `lower`, `trim`, `trimStart`, `trimEnd`, `split(delimiter)`, `replace(old, new)`, `startsWith(prefix)`, `endsWith(suffix)`, `contains(substr)`, `length`, `charAt(index)`, `substring(start, end?)`
|
||||||
|
- **StringList metodları:** `length`/`len`, `isEmpty`, `first`, `last`, `get(index)`, `contains(value)`, `indexOf(value)`, `slice(start, end?)`, `reverse()`, `sort()`, `join(delimiter?)`
|
||||||
|
- **NumberList metodları:** `length`/`len`, `isEmpty`, `first`, `last`, `get(index)`, `contains(value)`, `indexOf(value)`, `slice(start, end?)`, `reverse()`, `sort()`, `sum`, `avg`, `min`, `max`
|
||||||
|
- **Object metodları:** `keys()`, `values()`, `length`/`len()`, `contains(key)`, `get(key)`
|
||||||
|
- **Harici metodlar:** Yukarıdaki built-in metodlar bulunamazsa `external_methods` HashMap'inde aranır
|
||||||
|
|
||||||
|
### Üyelik Testi
|
||||||
|
- **`handle_contains()`** — `in` operatörü: String in StringList, Number in NumberList, String in String (substring), String in Object (anahtar varlığı kontrolü)
|
||||||
|
|
||||||
|
### Harici Fonksiyonlar ve Sonuç
|
||||||
|
- **`handle_call_external()`** — İsimle harici fonksiyon çağır (HashMap lookup)
|
||||||
|
- **`handle_set_result()`** — ExprStmt sonucunu `last_result`'a kaydet
|
||||||
|
|
||||||
|
### Built-in
|
||||||
|
- **`handle_log()`** — Register değerini stdout'a yazdır
|
||||||
|
- **`rand(min, max)`** — min ile max arasında rastgele tamsayı üret (varsayılan harici fonksiyon)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Yardımcı Metodlar
|
||||||
|
|
||||||
|
| Metod | Açıklama |
|
||||||
|
|-------|----------|
|
||||||
|
| `read_register_checked()` | Register oku ve doğrula |
|
||||||
|
| `validate_register()` | Register indeks sınır kontrolü |
|
||||||
|
| `read_jump_address()` | 4-byte adres oku ve sınır kontrolü yap |
|
||||||
|
| `set_position(addr)` | Reader pozisyonunu doğrulayarak ayarla |
|
||||||
|
| `wrap_error(err)` | Hataya kaynak konum bilgisi ekle |
|
||||||
|
| `debug_print_state()` | Debug çıktısı (debug build) |
|
||||||
|
| `print_profile_summary()` | Opcode çalışma sayıları (debug build) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Harici Fonksiyon ve Metod Kaydı
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Harici fonksiyon
|
||||||
|
vm.register_function("getRate", |args| {
|
||||||
|
match &args[0] {
|
||||||
|
Value::String(currency) => Ok(Value::Number(dec!(34.5))),
|
||||||
|
_ => Err("expected string".to_string()),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tipe özel harici metod
|
||||||
|
vm.register_method("Number", "format", |this, args| {
|
||||||
|
// this: &Value, args: &[Value]
|
||||||
|
Ok(Value::String("formatted".into()))
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tip isimleri:** `"Number"`, `"String"`, `"Boolean"`, `"NumberList"`, `"StringList"`, `"Object"`, `"Null"`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Çalışma Modeli Özeti
|
||||||
|
|
||||||
|
- **Register tabanlı:** 8 register ile hesaplama
|
||||||
|
- **Global depo:** SmolStr → Value map'i
|
||||||
|
- **Harici fonksiyonlar:** İsimle çözümlenen host fonksiyonları (HashMap lookup)
|
||||||
|
- **Harici metodlar:** Tipe özel host metodları
|
||||||
|
- **Expression return:** Son ExprStmt'ın değeri `execute()` dönüş değeri olarak verilir
|
||||||
|
- **Dinamik tip sistemi:** Tip uyuşmazlıklarında çalışma zamanı hatası
|
||||||
257
editor/bun.lock
Normal file
257
editor/bun.lock
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "codemirror-lang-dexpr",
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/autocomplete": "^6.0.0",
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.0.0",
|
||||||
|
"@lezer/generator": "^1.8.0",
|
||||||
|
"@lezer/highlight": "^1.0.0",
|
||||||
|
"@lezer/lr": "^1.4.8",
|
||||||
|
"codemirror": "^6.0.2",
|
||||||
|
"tsup": "^8.0.0",
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@codemirror/autocomplete": "^6.0.0",
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.0.0",
|
||||||
|
"@lezer/highlight": "^1.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@codemirror/autocomplete": ["@codemirror/autocomplete@6.20.1", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A=="],
|
||||||
|
|
||||||
|
"@codemirror/commands": ["@codemirror/commands@6.10.3", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.6.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q=="],
|
||||||
|
|
||||||
|
"@codemirror/language": ["@codemirror/language@6.12.3", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA=="],
|
||||||
|
|
||||||
|
"@codemirror/lint": ["@codemirror/lint@6.9.5", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", "crelt": "^1.0.5" } }, "sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA=="],
|
||||||
|
|
||||||
|
"@codemirror/search": ["@codemirror/search@6.6.0", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw=="],
|
||||||
|
|
||||||
|
"@codemirror/state": ["@codemirror/state@6.6.0", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ=="],
|
||||||
|
|
||||||
|
"@codemirror/view": ["@codemirror/view@6.41.0", "", { "dependencies": { "@codemirror/state": "^6.6.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-6H/qadXsVuDY219Yljhohglve8xf4B8xJkVOEWfA5uiYKiTFppjqsvsfR5iPA0RbvRBoOyTZpbLIxe9+0UR8xA=="],
|
||||||
|
|
||||||
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="],
|
||||||
|
|
||||||
|
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="],
|
||||||
|
|
||||||
|
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="],
|
||||||
|
|
||||||
|
"@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="],
|
||||||
|
|
||||||
|
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="],
|
||||||
|
|
||||||
|
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="],
|
||||||
|
|
||||||
|
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="],
|
||||||
|
|
||||||
|
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="],
|
||||||
|
|
||||||
|
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="],
|
||||||
|
|
||||||
|
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="],
|
||||||
|
|
||||||
|
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="],
|
||||||
|
|
||||||
|
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="],
|
||||||
|
|
||||||
|
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="],
|
||||||
|
|
||||||
|
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="],
|
||||||
|
|
||||||
|
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="],
|
||||||
|
|
||||||
|
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="],
|
||||||
|
|
||||||
|
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="],
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||||
|
|
||||||
|
"@lezer/common": ["@lezer/common@1.5.1", "", {}, "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw=="],
|
||||||
|
|
||||||
|
"@lezer/generator": ["@lezer/generator@1.8.0", "", { "dependencies": { "@lezer/common": "^1.1.0", "@lezer/lr": "^1.3.0" }, "bin": { "lezer-generator": "src/lezer-generator.cjs" } }, "sha512-/SF4EDWowPqV1jOgoGSGTIFsE7Ezdr7ZYxyihl5eMKVO5tlnpIhFcDavgm1hHY5GEonoOAEnJ0CU0x+tvuAuUg=="],
|
||||||
|
|
||||||
|
"@lezer/highlight": ["@lezer/highlight@1.2.3", "", { "dependencies": { "@lezer/common": "^1.3.0" } }, "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g=="],
|
||||||
|
|
||||||
|
"@lezer/lr": ["@lezer/lr@1.4.8", "", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA=="],
|
||||||
|
|
||||||
|
"@marijn/find-cluster-break": ["@marijn/find-cluster-break@1.0.2", "", {}, "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.1", "", { "os": "android", "cpu": "arm" }, "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.1", "", { "os": "android", "cpu": "arm64" }, "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg=="],
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ=="],
|
||||||
|
|
||||||
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
|
"acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
|
||||||
|
|
||||||
|
"any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
|
||||||
|
|
||||||
|
"bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="],
|
||||||
|
|
||||||
|
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
|
||||||
|
|
||||||
|
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||||
|
|
||||||
|
"codemirror": ["codemirror@6.0.2", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/lint": "^6.0.0", "@codemirror/search": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" } }, "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw=="],
|
||||||
|
|
||||||
|
"commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
||||||
|
|
||||||
|
"confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
||||||
|
|
||||||
|
"consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
|
||||||
|
|
||||||
|
"crelt": ["crelt@1.0.6", "", {}, "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="],
|
||||||
|
|
||||||
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
|
"esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="],
|
||||||
|
|
||||||
|
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||||
|
|
||||||
|
"fix-dts-default-cjs-exports": ["fix-dts-default-cjs-exports@1.0.1", "", { "dependencies": { "magic-string": "^0.30.17", "mlly": "^1.7.4", "rollup": "^4.34.8" } }, "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg=="],
|
||||||
|
|
||||||
|
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||||
|
|
||||||
|
"joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="],
|
||||||
|
|
||||||
|
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
||||||
|
|
||||||
|
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||||
|
|
||||||
|
"load-tsconfig": ["load-tsconfig@0.2.5", "", {}, "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg=="],
|
||||||
|
|
||||||
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
|
|
||||||
|
"mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="],
|
||||||
|
|
||||||
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
|
"mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
|
||||||
|
|
||||||
|
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||||
|
|
||||||
|
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||||
|
|
||||||
|
"picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
|
||||||
|
|
||||||
|
"pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
|
||||||
|
|
||||||
|
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||||
|
|
||||||
|
"postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="],
|
||||||
|
|
||||||
|
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||||
|
|
||||||
|
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
||||||
|
|
||||||
|
"rollup": ["rollup@4.60.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.1", "@rollup/rollup-android-arm64": "4.60.1", "@rollup/rollup-darwin-arm64": "4.60.1", "@rollup/rollup-darwin-x64": "4.60.1", "@rollup/rollup-freebsd-arm64": "4.60.1", "@rollup/rollup-freebsd-x64": "4.60.1", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", "@rollup/rollup-linux-arm-musleabihf": "4.60.1", "@rollup/rollup-linux-arm64-gnu": "4.60.1", "@rollup/rollup-linux-arm64-musl": "4.60.1", "@rollup/rollup-linux-loong64-gnu": "4.60.1", "@rollup/rollup-linux-loong64-musl": "4.60.1", "@rollup/rollup-linux-ppc64-gnu": "4.60.1", "@rollup/rollup-linux-ppc64-musl": "4.60.1", "@rollup/rollup-linux-riscv64-gnu": "4.60.1", "@rollup/rollup-linux-riscv64-musl": "4.60.1", "@rollup/rollup-linux-s390x-gnu": "4.60.1", "@rollup/rollup-linux-x64-gnu": "4.60.1", "@rollup/rollup-linux-x64-musl": "4.60.1", "@rollup/rollup-openbsd-x64": "4.60.1", "@rollup/rollup-openharmony-arm64": "4.60.1", "@rollup/rollup-win32-arm64-msvc": "4.60.1", "@rollup/rollup-win32-ia32-msvc": "4.60.1", "@rollup/rollup-win32-x64-gnu": "4.60.1", "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w=="],
|
||||||
|
|
||||||
|
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
|
||||||
|
|
||||||
|
"style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="],
|
||||||
|
|
||||||
|
"sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
|
||||||
|
|
||||||
|
"thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
|
||||||
|
|
||||||
|
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
|
||||||
|
|
||||||
|
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
|
||||||
|
|
||||||
|
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||||
|
|
||||||
|
"tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
|
||||||
|
|
||||||
|
"ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],
|
||||||
|
|
||||||
|
"tsup": ["tsup@8.5.1", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.27.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "^0.7.6", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
"ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
|
||||||
|
|
||||||
|
"w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
19
editor/demo.html
Normal file
19
editor/demo.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>dexpr Editor Demo</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: system-ui; max-width: 800px; margin: 40px auto; padding: 0 20px; }
|
||||||
|
h1 { font-size: 1.4rem; }
|
||||||
|
#editor { border: 1px solid #ccc; border-radius: 4px; }
|
||||||
|
.info { color: #666; font-size: 0.85rem; margin-top: 8px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>dexpr Editor</h1>
|
||||||
|
<div id="editor"></div>
|
||||||
|
<p class="info">Type to see syntax highlighting. Press Ctrl+Space for autocomplete. Try typing a dot after a variable for method suggestions.</p>
|
||||||
|
<script src="dist/demo.global.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
151
editor/demo.ts
Normal file
151
editor/demo.ts
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import { EditorView, basicSetup } from "codemirror";
|
||||||
|
import { EditorState } from "@codemirror/state";
|
||||||
|
import { dexpr, DexprLanguageInfo } from "./src/index";
|
||||||
|
|
||||||
|
// ── Simulate: this JSON comes from Rust's LanguageInfo::to_json() ──
|
||||||
|
// In a real app:
|
||||||
|
// Rust: info.add_value("customer", &Value::from_json(json)?, None);
|
||||||
|
// let metadata = info.to_json();
|
||||||
|
// HTTP: GET /api/editor-metadata → metadata
|
||||||
|
// JS: const languageInfo = await fetch(...).then(r => r.json());
|
||||||
|
//
|
||||||
|
// Here we inline it for the demo:
|
||||||
|
|
||||||
|
const languageInfo: DexprLanguageInfo = {
|
||||||
|
functions: [
|
||||||
|
{ name: "log", signature: "(...args) -> null", doc: "Print values to output" },
|
||||||
|
{ name: "rand", signature: "(min, max) -> Number", doc: "Random integer between min and max" },
|
||||||
|
{ name: "getRate", signature: "(code: String) -> Number", doc: "Get exchange rate for currency" },
|
||||||
|
],
|
||||||
|
methods: {
|
||||||
|
String: [
|
||||||
|
{ name: "upper", signature: "() -> String" },
|
||||||
|
{ name: "lower", signature: "() -> String" },
|
||||||
|
{ name: "trim", signature: "() -> String" },
|
||||||
|
{ name: "trimStart", signature: "() -> String" },
|
||||||
|
{ name: "trimEnd", signature: "() -> String" },
|
||||||
|
{ name: "split", signature: "(delim: String) -> StringList" },
|
||||||
|
{ name: "replace", signature: "(old: String, new: String) -> String" },
|
||||||
|
{ name: "contains", signature: "(substr: String) -> Boolean" },
|
||||||
|
{ name: "startsWith", signature: "(prefix: String) -> Boolean" },
|
||||||
|
{ name: "endsWith", signature: "(suffix: String) -> Boolean" },
|
||||||
|
{ name: "length", signature: "() -> Number" },
|
||||||
|
{ name: "charAt", signature: "(index: Number) -> String" },
|
||||||
|
{ name: "substring", signature: "(start: Number, end?: Number) -> String" },
|
||||||
|
],
|
||||||
|
Number: [],
|
||||||
|
Boolean: [],
|
||||||
|
Object: [
|
||||||
|
{ name: "keys", signature: "() -> StringList", doc: "Get all keys" },
|
||||||
|
{ name: "values", signature: "() -> StringList | NumberList", doc: "Get all values (must be same type)" },
|
||||||
|
{ name: "length", signature: "() -> Number", doc: "Number of entries" },
|
||||||
|
{ name: "len", signature: "() -> Number" },
|
||||||
|
{ name: "contains", signature: "(key: String) -> Boolean", doc: "Check if key exists" },
|
||||||
|
{ name: "get", signature: "(key: String) -> any", doc: "Get value by key" },
|
||||||
|
],
|
||||||
|
NumberList: [
|
||||||
|
{ name: "length", signature: "() -> Number" },
|
||||||
|
{ name: "len", signature: "() -> Number" },
|
||||||
|
{ name: "isEmpty", signature: "() -> Boolean" },
|
||||||
|
{ name: "first", signature: "() -> Number" },
|
||||||
|
{ name: "last", signature: "() -> Number" },
|
||||||
|
{ name: "get", signature: "(index: Number) -> Number" },
|
||||||
|
{ name: "contains", signature: "(value: Number) -> Boolean" },
|
||||||
|
{ name: "indexOf", signature: "(value: Number) -> Number" },
|
||||||
|
{ name: "slice", signature: "(start: Number, end?: Number) -> NumberList" },
|
||||||
|
{ name: "reverse", signature: "() -> NumberList" },
|
||||||
|
{ name: "sort", signature: "() -> NumberList" },
|
||||||
|
{ name: "sum", signature: "() -> Number" },
|
||||||
|
{ name: "avg", signature: "() -> Number" },
|
||||||
|
{ name: "min", signature: "() -> Number" },
|
||||||
|
{ name: "max", signature: "() -> Number" },
|
||||||
|
],
|
||||||
|
StringList: [
|
||||||
|
{ name: "length", signature: "() -> Number" },
|
||||||
|
{ name: "len", signature: "() -> Number" },
|
||||||
|
{ name: "isEmpty", signature: "() -> Boolean" },
|
||||||
|
{ name: "first", signature: "() -> String" },
|
||||||
|
{ name: "last", signature: "() -> String" },
|
||||||
|
{ name: "get", signature: "(index: Number) -> String" },
|
||||||
|
{ name: "contains", signature: "(value: String) -> Boolean" },
|
||||||
|
{ name: "indexOf", signature: "(value: String) -> Number" },
|
||||||
|
{ name: "slice", signature: "(start: Number, end?: Number) -> StringList" },
|
||||||
|
{ name: "reverse", signature: "() -> StringList" },
|
||||||
|
{ name: "sort", signature: "() -> StringList" },
|
||||||
|
{ name: "join", signature: "(delim?: String) -> String" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// ── Variables: as if Rust did info.add_value("customer", &Value::from_json(...), ...) ──
|
||||||
|
variables: [
|
||||||
|
// info.add_value("discount", &Value::Number(10), None)
|
||||||
|
{ name: "discount", type: "Number", doc: "Discount percentage" },
|
||||||
|
// info.add_value("customer", &Value::from_json(r#"{"name":"Alice",...}"#)?, None)
|
||||||
|
// → from_json auto-detects field types from the JSON values
|
||||||
|
{
|
||||||
|
name: "customer", type: "Object", doc: "Customer — from JSON via Value::from_json()",
|
||||||
|
fields: [
|
||||||
|
{ name: "name", type: "String" },
|
||||||
|
{ name: "email", type: "String" },
|
||||||
|
{ name: "city", type: "String" },
|
||||||
|
{ name: "age", type: "Number" },
|
||||||
|
{ name: "active", type: "Boolean" },
|
||||||
|
{ name: "tags", type: "StringList" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// info.add_value("order", &Value::from_json(r#"{"amount":1500,...}"#)?, None)
|
||||||
|
{
|
||||||
|
name: "order", type: "Object", doc: "Order — from JSON via Value::from_json()",
|
||||||
|
fields: [
|
||||||
|
{ name: "amount", type: "Number" },
|
||||||
|
{ name: "currency", type: "String" },
|
||||||
|
{ name: "status", type: "String" },
|
||||||
|
{ name: "items", type: "StringList" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const sampleCode = `// dexpr demo
|
||||||
|
// customer and order come from JSON via Value::from_json()
|
||||||
|
// Rust side:
|
||||||
|
// let customer = Value::from_json(api_response)?;
|
||||||
|
// vm.set_global("customer", customer.clone());
|
||||||
|
// info.add_value("customer", &customer, None);
|
||||||
|
|
||||||
|
// Property access — type-aware autocomplete
|
||||||
|
name = customer.name
|
||||||
|
city = customer.city
|
||||||
|
|
||||||
|
// Object fields in expressions
|
||||||
|
net = order.amount * (1 - discount / 100)
|
||||||
|
|
||||||
|
// Method chaining: obj.field → String methods
|
||||||
|
upper_name = customer.name.upper()
|
||||||
|
domain = customer.email.split("@").last()
|
||||||
|
|
||||||
|
// Object methods
|
||||||
|
fields = customer.keys()
|
||||||
|
fieldCount = customer.length()
|
||||||
|
|
||||||
|
// in operator — check key existence
|
||||||
|
if "email" in customer then
|
||||||
|
log(customer.email)
|
||||||
|
end
|
||||||
|
|
||||||
|
// Property assignment
|
||||||
|
customer.city = "Ankara"
|
||||||
|
|
||||||
|
// List field methods
|
||||||
|
first_tag = customer.tags.first()
|
||||||
|
tag_count = customer.tags.length()
|
||||||
|
|
||||||
|
log(upper_name, net, first_tag)
|
||||||
|
`;
|
||||||
|
|
||||||
|
new EditorView({
|
||||||
|
state: EditorState.create({
|
||||||
|
doc: sampleCode,
|
||||||
|
extensions: [basicSetup, dexpr(languageInfo)],
|
||||||
|
}),
|
||||||
|
parent: document.getElementById("editor")!,
|
||||||
|
});
|
||||||
24777
editor/dist/demo.global.js
vendored
Normal file
24777
editor/dist/demo.global.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
462
editor/dist/index.cjs
vendored
Normal file
462
editor/dist/index.cjs
vendored
Normal file
@@ -0,0 +1,462 @@
|
|||||||
|
"use strict";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
|
||||||
|
// src/index.ts
|
||||||
|
var index_exports = {};
|
||||||
|
__export(index_exports, {
|
||||||
|
KEYWORDS: () => KEYWORDS,
|
||||||
|
dexpr: () => dexpr,
|
||||||
|
dexprCompletion: () => dexprCompletion,
|
||||||
|
dexprHighlightStyle: () => dexprHighlightStyle,
|
||||||
|
dexprHighlighting: () => dexprHighlighting2,
|
||||||
|
dexprLanguage: () => dexprLanguage
|
||||||
|
});
|
||||||
|
module.exports = __toCommonJS(index_exports);
|
||||||
|
var import_language4 = require("@codemirror/language");
|
||||||
|
|
||||||
|
// src/language.ts
|
||||||
|
var import_language = require("@codemirror/language");
|
||||||
|
var import_highlight = require("@lezer/highlight");
|
||||||
|
|
||||||
|
// src/parser.js
|
||||||
|
var import_lr2 = require("@lezer/lr");
|
||||||
|
|
||||||
|
// src/tokens.ts
|
||||||
|
var import_lr = require("@lezer/lr");
|
||||||
|
|
||||||
|
// src/parser.terms.js
|
||||||
|
var elseIf = 44;
|
||||||
|
|
||||||
|
// src/tokens.ts
|
||||||
|
var CH_e = 101;
|
||||||
|
var CH_l = 108;
|
||||||
|
var CH_s = 115;
|
||||||
|
var CH_i = 105;
|
||||||
|
var CH_f = 102;
|
||||||
|
var CH_SPACE = 32;
|
||||||
|
var CH_TAB = 9;
|
||||||
|
var CH_NL = 10;
|
||||||
|
var CH_CR = 13;
|
||||||
|
var elseIfTokenizer = new import_lr.ExternalTokenizer((input) => {
|
||||||
|
if (input.next !== CH_e) return;
|
||||||
|
if (input.peek(1) !== CH_l) return;
|
||||||
|
if (input.peek(2) !== CH_s) return;
|
||||||
|
if (input.peek(3) !== CH_e) return;
|
||||||
|
let pos = 4;
|
||||||
|
const ch = input.peek(pos);
|
||||||
|
if (ch !== CH_SPACE && ch !== CH_TAB && ch !== CH_NL && ch !== CH_CR) return;
|
||||||
|
while (true) {
|
||||||
|
const c = input.peek(pos);
|
||||||
|
if (c === CH_SPACE || c === CH_TAB || c === CH_NL || c === CH_CR) {
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (input.peek(pos) !== CH_i) return;
|
||||||
|
if (input.peek(pos + 1) !== CH_f) return;
|
||||||
|
const after = input.peek(pos + 2);
|
||||||
|
if (after >= 97 && after <= 122 || // a-z
|
||||||
|
after >= 65 && after <= 90 || // A-Z
|
||||||
|
after >= 48 && after <= 57 || // 0-9
|
||||||
|
after === 95)
|
||||||
|
return;
|
||||||
|
input.acceptToken(elseIf, pos + 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// src/parser.js
|
||||||
|
var spec_identifier = { __proto__: null, if: 11, true: 21, false: 21, in: 43, then: 69, else: 71, end: 73 };
|
||||||
|
var parser = import_lr2.LRParser.deserialize({
|
||||||
|
version: 14,
|
||||||
|
states: "+^Q]QQOOOOQP'#Cb'#CbOOQP'#Ce'#CeOwQQO'#CiO`QQO'#CjO#TQRO'#DTO%bQRO'#D_OOQP'#D_'#D_O%iQRO'#D_OOQP'#D]'#D]OOQP'#DU'#DUQ]QQOOOwQQO'#C`O&eQQO,59TO&lQRO'#D_O(zQRO,59UO`QQO,59XO`QQO,59XO`QQO,59XO`QQO,59XO`QQO,59XO)wQQO,59hO)|QQO'#CzOOQP,59i,59iO`QQO,59mOOQP-E7S-E7SO*TQQO,58zOOQP1G.o1G.oO+oQRO1G.sO+vQRO1G.sO-bQRO1G.sO-iQRO1G.sO.[QRO1G.sOOQP'#Cy'#CyOOQP1G/S1G/SO/[QQO'#D`OOQP,59f,59fO/fQQO,59fO/kQRO1G/XO0bQRO1G.fO0oQQO1G/SOOQP7+$i7+$iOwQQO'#DVO1pQQO,59zOOQP1G/Q1G/QO1xQRO7+$QO2TQRO7+$QOwQQO'#DWOOQP7+$Q7+$QO2bQQO7+$QO2iQQO,59qOOQO-E7T-E7TOOQP-E7U-E7UOOQP<<Gl<<GlO2sQQO<<GlO2zQRO<<GlO3VQQO,59rO2sQQO<<GlO3^QQOAN=WOOQPAN=WAN=WO3^QQOAN=WO3eQRO1G/^OOQPG22rG22rO3rQQOG22rO3yQRO7+$xOOQPLD(^LD(^O)wQQO,59hO5RQQO1G.sO5YQQO1G.sO6[QQO1G.sO6cQQO1G.sO6jQQO1G.sO7QQQO,59UOwQQO,59XOwQQO,59XOwQQO,59XOwQQO,59XOwQQO,59XOwQQO'#Cj",
|
||||||
|
stateData: "7n~O!OOSPOSQOS~OT[OVVOWVOYQO[RO_SO`SO!QPO~OVVOWVOYQO[RO_!pO`!pO!QPO~O_cOb`OcaOdbOebOfcOgdOhdOidOjdOleO~OTwXVwXWwXYwX[wX`wX{wX!QwXswXtwX|wX~P!`OvhOT!RXV!RXW!RXY!RX_!RX`!RXb!RXc!RXd!RXe!RXf!RXg!RXh!RXi!RXj!RXl!RX{!RX!Q!RXs!RXt!RX|!RX~O[fO~P#zO[!RX~P#zO_!nOb!kOc!lOd!mOe!mOf!nOg!oOh!oOi!oOj!oOl!dO~OZkO~P%pO[fOZ!RX_!RXb!RXc!RXd!RXe!RXf!RXg!RXh!RXi!RXj!RXl!RXT!RXV!RXW!RXY!RX`!RX{!RX!Q!RXr!RXo!RXs!RXt!RX|!RX~Ob^ac^ad^ae^af^ag^ah^ai^aj^a~O_cOleOT^aV^aW^aY^a[^a`^a{^a!Q^as^at^a|^a~P(]O!QqO~OZtO~PwOrwO~P%pO_cOdbOebOfcOgdOhdOidOjdOleOTaiVaiWaiYai[ai`aibai{ai!Qaisaitai|ai~OcaO~P*[Ocai~P*[O_cOgdOhdOidOjdOleOTaiVaiWaiYai[ai`aibaicaidaieai{ai!Qaisaitai|ai~OfcO~P+}Ofai~P+}Obaicaidaieaifaigaihaiiai~O_cOjdOleOTaiVaiWaiYai[ai`ai{ai!Qaisaitai|ai~P-pOozOZ!SX~P%pOZ|O~OTuiVuiWuiYui[ui`ui{ui!Quisuitui|ui~P!`Os!ROt!QO|!PO~P]O[fOZpi_pibpicpidpiepifpigpihpiipijpilpirpiopi~OozOZ!Sa~Os!WOt!VO|!PO~Os!WOt!VO|!PO~P]Ot!VO~P]OZyaoya~P%pOt!]O~P]Os!^Ot!]O|!PO~Or!_O~P%pOt!`O~P]Oszitzi|zi~P]Ot!cO~P]Oszqtzq|zq~P]O_!nOd!mOe!mOf!nOg!oOh!oOi!oOj!oOl!dOZaibairaioai~Oc!lO~P4WOcai~P4WO_!nOg!oOh!oOi!oOj!oOl!dOZaibaicaidaieairaioai~Of!nO~P5aOfai~P5aO_!nOj!oOl!dOZairaioai~P-pO_!nOl!dOZ^ar^ao^a~P(]OvdjgQPQh~",
|
||||||
|
goto: "'n!TPPPP!UP!dPP#WPPP#W#WPP#WPPPPPPPPP#WP#x$OP$V#WPPP!UP!U$y%e%kPPPP%uP&T'kiXOZw!O!R!W!Z![!^!_!a!bhUOZw!O!R!W!Z![!^!_!a!bu^RS[`abcdfhz!P!k!l!m!n!o!p!_VORSZ[`abcdfhwz!O!P!R!W!Z![!^!_!a!b!k!l!m!n!o!pQreRx!dSgU^RyxtVRS[`abcdfhz!P!k!l!m!n!o!piWOZw!O!R!W!Z![!^!_!a!bQZO[iZ!O!Z![!a!bQ!OwQ!Z!RQ![!WQ!a!^R!b!_Q{sR!T{Q}wS!U}!XR!X!OiYOZw!O!R!W!Z![!^!_!a!bhTOZw!O!R!W!Z![!^!_!a!bQ]RQ_SQj[Ql`QmaQnbQocQpdQsfQvhQ!SzQ!Y!PQ!e!kQ!f!lQ!g!mQ!h!nQ!i!oR!j!pRuf",
|
||||||
|
nodeNames: "\u26A0 LineComment BlockComment Program IfStatement if VariableName Number String BooleanLiteral BooleanLiteral ) ( ParenExpression UnaryExpression - ! BinaryExpression || && CompareOp in + * / % Power MethodCall . PropertyName ArgList , PropertyAccess FunctionCall then else end Assignment AssignOp ExprStatement",
|
||||||
|
maxTerm: 50,
|
||||||
|
nodeProps: [
|
||||||
|
["group", -3, 4, 37, 39, "Statement", -10, 6, 7, 8, 9, 13, 14, 17, 27, 32, 33, "Expression"],
|
||||||
|
["openedBy", 11, "("],
|
||||||
|
["closedBy", 12, ")"]
|
||||||
|
],
|
||||||
|
skippedNodes: [0, 1, 2],
|
||||||
|
repeatNodeCount: 3,
|
||||||
|
tokenData: "+p~RiXY!pYZ!p]^!ppq!pqr#Rrs#`uv%Svw%awx%lxy'Zyz'`z{'e{|'u|}'}}!O(S!O!P([!P!Q(a!Q![*X!^!_*r!_!`*z!`!a*r!c!}+S#R#S+S#T#o+S#p#q+e~!uS!O~XY!pYZ!p]^!ppq!p~#WP`~!_!`#Z~#`Od~~#cWOY#`Zr#`rs#{s#O#`#O#P$Q#P;'S#`;'S;=`$|<%lO#`~$QOW~~$TRO;'S#`;'S;=`$^;=`O#`~$aXOY#`Zr#`rs#{s#O#`#O#P$Q#P;'S#`;'S;=`$|;=`<%l#`<%lO#`~%PP;=`<%l#`~%XPi~!_!`%[~%aOv~~%dPvw%g~%lOc~~%oWOY%lZw%lwx#{x#O%l#O#P&X#P;'S%l;'S;=`'T<%lO%l~&[RO;'S%l;'S;=`&e;=`O%l~&hXOY%lZw%lwx#{x#O%l#O#P&X#P;'S%l;'S;=`'T;=`<%l%l<%lO%l~'WP;=`<%l%l~'`O[~~'eOZ~~'jQg~z{'p!_!`%[~'uOj~~'zPf~!_!`%[~(SOo~~(XP_~!_!`%[~(aOl~~(fRh~z{(o!P!Q)p!_!`%[~(rTOz(oz{)R{;'S(o;'S;=`)j<%lO(o~)UTO!P(o!P!Q)e!Q;'S(o;'S;=`)j<%lO(o~)jOQ~~)mP;=`<%l(o~)uSP~OY)pZ;'S)p;'S;=`*R<%lO)p~*UP;=`<%l)p~*^QV~!O!P*d!Q![*X~*gP!Q![*j~*oPV~!Q![*j~*wPd~!_!`#Z~+PPv~!_!`#Z~+XS!Q~!Q![+S!c!}+S#R#S+S#T#o+S~+hP#p#q+k~+pOb~",
|
||||||
|
tokenizers: [elseIfTokenizer, 0],
|
||||||
|
topRules: { "Program": [0, 3] },
|
||||||
|
specialized: [{ term: 48, get: (value) => spec_identifier[value] || -1 }],
|
||||||
|
tokenPrec: 1033
|
||||||
|
});
|
||||||
|
|
||||||
|
// src/language.ts
|
||||||
|
var dexprHighlighting = (0, import_highlight.styleTags)({
|
||||||
|
"if then else end in elseIf": import_highlight.tags.keyword,
|
||||||
|
BooleanLiteral: import_highlight.tags.bool,
|
||||||
|
String: import_highlight.tags.string,
|
||||||
|
Number: import_highlight.tags.number,
|
||||||
|
LineComment: import_highlight.tags.lineComment,
|
||||||
|
BlockComment: import_highlight.tags.blockComment,
|
||||||
|
"CompareOp AssignOp Power": import_highlight.tags.compareOperator,
|
||||||
|
'"+" "-" "*" "/" "%" "!" "||" "&&"': import_highlight.tags.operator,
|
||||||
|
VariableName: import_highlight.tags.variableName,
|
||||||
|
PropertyName: import_highlight.tags.propertyName,
|
||||||
|
"FunctionCall/VariableName": import_highlight.tags.function(import_highlight.tags.variableName),
|
||||||
|
'"(" ")"': import_highlight.tags.paren,
|
||||||
|
'","': import_highlight.tags.separator,
|
||||||
|
'"."': import_highlight.tags.derefOperator
|
||||||
|
});
|
||||||
|
var dexprLanguage = import_language.LRLanguage.define({
|
||||||
|
name: "dexpr",
|
||||||
|
parser: parser.configure({
|
||||||
|
props: [dexprHighlighting]
|
||||||
|
}),
|
||||||
|
languageData: {
|
||||||
|
commentTokens: { line: "//", block: { open: "/*", close: "*/" } },
|
||||||
|
closeBrackets: { brackets: ["(", '"', "'"] }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// src/completions.ts
|
||||||
|
var import_autocomplete = require("@codemirror/autocomplete");
|
||||||
|
var import_language2 = require("@codemirror/language");
|
||||||
|
function funcToCompletion(f) {
|
||||||
|
return {
|
||||||
|
label: f.name,
|
||||||
|
type: "function",
|
||||||
|
detail: f.signature,
|
||||||
|
info: f.doc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function methodToCompletion(m) {
|
||||||
|
return {
|
||||||
|
label: m.name,
|
||||||
|
type: "method",
|
||||||
|
detail: m.signature,
|
||||||
|
info: m.doc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function varToCompletion(v) {
|
||||||
|
return {
|
||||||
|
label: v.name,
|
||||||
|
type: "variable",
|
||||||
|
detail: v.type,
|
||||||
|
info: v.doc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var KEYWORDS = [
|
||||||
|
{ label: "if", type: "keyword" },
|
||||||
|
{ label: "then", type: "keyword" },
|
||||||
|
{ label: "else", type: "keyword" },
|
||||||
|
{ label: "end", type: "keyword" },
|
||||||
|
{ label: "true", type: "keyword", detail: "Boolean" },
|
||||||
|
{ label: "false", type: "keyword", detail: "Boolean" },
|
||||||
|
{ label: "in", type: "keyword", detail: "membership test" }
|
||||||
|
];
|
||||||
|
function inferVariableTypes(context, knownVars) {
|
||||||
|
const types = new Map(knownVars);
|
||||||
|
const tree = (0, import_language2.syntaxTree)(context.state);
|
||||||
|
const doc = context.state.doc;
|
||||||
|
tree.iterate({
|
||||||
|
enter(node) {
|
||||||
|
if (node.name !== "Assignment") return;
|
||||||
|
const varNode = node.node.firstChild;
|
||||||
|
if (!varNode || varNode.name !== "VariableName") return;
|
||||||
|
const varName = doc.sliceString(varNode.from, varNode.to);
|
||||||
|
const assignOp = varNode.nextSibling;
|
||||||
|
if (!assignOp) return;
|
||||||
|
const exprNode = assignOp.nextSibling;
|
||||||
|
if (!exprNode) return;
|
||||||
|
const exprType = inferExprType(exprNode, doc, types);
|
||||||
|
if (exprType) types.set(varName, exprType);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
function inferExprType(node, doc, knownTypes) {
|
||||||
|
switch (node.name) {
|
||||||
|
case "String":
|
||||||
|
return "String";
|
||||||
|
case "Number":
|
||||||
|
return "Number";
|
||||||
|
case "BooleanLiteral":
|
||||||
|
return "Boolean";
|
||||||
|
case "VariableName": {
|
||||||
|
const name = doc.sliceString(node.from, node.to);
|
||||||
|
return knownTypes.get(name) ?? null;
|
||||||
|
}
|
||||||
|
case "MethodCall": {
|
||||||
|
const propNode = findChild(node, "PropertyName");
|
||||||
|
if (!propNode) return null;
|
||||||
|
const method = doc.sliceString(propNode.from, propNode.to);
|
||||||
|
return inferMethodReturnType(method);
|
||||||
|
}
|
||||||
|
case "BinaryExpression": {
|
||||||
|
const first = node.firstChild;
|
||||||
|
if (first) {
|
||||||
|
const t = inferExprType(first, doc, knownTypes);
|
||||||
|
if (t === "String") return "String";
|
||||||
|
if (t === "Number") return "Number";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case "PropertyAccess": {
|
||||||
|
const objNode = node.firstChild;
|
||||||
|
const propNode = findChild(node, "PropertyName");
|
||||||
|
if (!objNode || !propNode) return null;
|
||||||
|
if (objNode.name === "VariableName") {
|
||||||
|
const varName = doc.sliceString(objNode.from, objNode.to);
|
||||||
|
const fieldName = doc.sliceString(propNode.from, propNode.to);
|
||||||
|
const rootType = knownTypes.get(varName);
|
||||||
|
if (rootType === "Object") {
|
||||||
|
return knownTypes.get(`${varName}.${fieldName}`) ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case "FunctionCall":
|
||||||
|
case "ParenExpression":
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function findChild(node, name) {
|
||||||
|
let child = node.firstChild;
|
||||||
|
while (child) {
|
||||||
|
if (child.name === name) return child;
|
||||||
|
child = child.nextSibling;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function inferMethodReturnType(method) {
|
||||||
|
switch (method) {
|
||||||
|
// String -> String
|
||||||
|
case "upper":
|
||||||
|
case "lower":
|
||||||
|
case "trim":
|
||||||
|
case "trimStart":
|
||||||
|
case "trimEnd":
|
||||||
|
case "replace":
|
||||||
|
case "charAt":
|
||||||
|
case "substring":
|
||||||
|
return "String";
|
||||||
|
// String -> Boolean
|
||||||
|
case "contains":
|
||||||
|
case "startsWith":
|
||||||
|
case "endsWith":
|
||||||
|
case "isEmpty":
|
||||||
|
return "Boolean";
|
||||||
|
// String -> Number
|
||||||
|
case "length":
|
||||||
|
case "len":
|
||||||
|
case "indexOf":
|
||||||
|
return "Number";
|
||||||
|
// String -> StringList
|
||||||
|
case "split":
|
||||||
|
return "StringList";
|
||||||
|
// List -> aggregate
|
||||||
|
case "sum":
|
||||||
|
case "avg":
|
||||||
|
case "min":
|
||||||
|
case "max":
|
||||||
|
case "first":
|
||||||
|
case "last":
|
||||||
|
return "Number";
|
||||||
|
// List methods returning lists
|
||||||
|
case "reverse":
|
||||||
|
case "sort":
|
||||||
|
case "slice":
|
||||||
|
return null;
|
||||||
|
// depends on input type
|
||||||
|
case "join":
|
||||||
|
return "String";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function dedup(items) {
|
||||||
|
const seen = /* @__PURE__ */ new Set();
|
||||||
|
return items.filter((item) => {
|
||||||
|
if (seen.has(item.label)) return false;
|
||||||
|
seen.add(item.label);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function dexprCompletion(info) {
|
||||||
|
const functionCompletions = info.functions.map(funcToCompletion);
|
||||||
|
const variableCompletions = (info.variables ?? []).map(varToCompletion);
|
||||||
|
const methodsByType = {};
|
||||||
|
for (const [type, methods] of Object.entries(info.methods)) {
|
||||||
|
methodsByType[type] = (methods ?? []).map(methodToCompletion);
|
||||||
|
}
|
||||||
|
const allMethods = dedup(
|
||||||
|
Object.values(methodsByType).flat()
|
||||||
|
);
|
||||||
|
const allIdentifiers = [
|
||||||
|
...KEYWORDS,
|
||||||
|
...functionCompletions,
|
||||||
|
...variableCompletions
|
||||||
|
];
|
||||||
|
const configVarTypes = /* @__PURE__ */ new Map();
|
||||||
|
for (const v of info.variables ?? []) {
|
||||||
|
configVarTypes.set(v.name, v.type);
|
||||||
|
}
|
||||||
|
const objectFieldCompletions = /* @__PURE__ */ new Map();
|
||||||
|
for (const v of info.variables ?? []) {
|
||||||
|
if (v.type === "Object" && v.fields) {
|
||||||
|
const fieldItems = [];
|
||||||
|
for (const f of v.fields) {
|
||||||
|
configVarTypes.set(`${v.name}.${f.name}`, f.type);
|
||||||
|
fieldItems.push({
|
||||||
|
label: f.name,
|
||||||
|
type: "property",
|
||||||
|
detail: f.type
|
||||||
|
});
|
||||||
|
}
|
||||||
|
objectFieldCompletions.set(v.name, fieldItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function resolveDotPath(context, dotPos, varTypes) {
|
||||||
|
const tree = (0, import_language2.syntaxTree)(context.state);
|
||||||
|
const doc = context.state.doc;
|
||||||
|
const path = [];
|
||||||
|
let pos = dotPos;
|
||||||
|
while (true) {
|
||||||
|
const nodeAtPos = tree.resolveInner(pos, -1);
|
||||||
|
if (nodeAtPos.name === "PropertyName") {
|
||||||
|
path.unshift(doc.sliceString(nodeAtPos.from, nodeAtPos.to));
|
||||||
|
const dotCharPos = nodeAtPos.from - 1;
|
||||||
|
if (dotCharPos >= 0 && doc.sliceString(dotCharPos, dotCharPos + 1) === ".") {
|
||||||
|
pos = dotCharPos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (nodeAtPos.name === "VariableName") {
|
||||||
|
path.unshift(doc.sliceString(nodeAtPos.from, nodeAtPos.to));
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (path.length === 0) return { type: null, path };
|
||||||
|
const rootType = varTypes.get(path[0]) ?? null;
|
||||||
|
if (path.length === 1) return { type: rootType, path };
|
||||||
|
let currentType = rootType;
|
||||||
|
for (let i = 1; i < path.length; i++) {
|
||||||
|
if (currentType !== "Object") {
|
||||||
|
return { type: currentType, path };
|
||||||
|
}
|
||||||
|
const key = `${path[i - 1]}.${path[i]}`;
|
||||||
|
const fieldType = varTypes.get(key) ?? null;
|
||||||
|
currentType = fieldType;
|
||||||
|
}
|
||||||
|
return { type: currentType, path };
|
||||||
|
}
|
||||||
|
function completions(context) {
|
||||||
|
const tree = (0, import_language2.syntaxTree)(context.state);
|
||||||
|
const node = tree.resolveInner(context.pos, -1);
|
||||||
|
if (node.name === "String" || node.name === "LineComment" || node.name === "BlockComment")
|
||||||
|
return null;
|
||||||
|
const dotMatch = context.matchBefore(/\.\w*/);
|
||||||
|
if (dotMatch) {
|
||||||
|
const dotPos = dotMatch.from;
|
||||||
|
const beforeNode = tree.resolveInner(dotPos, -1);
|
||||||
|
const varTypes = inferVariableTypes(context, configVarTypes);
|
||||||
|
if (beforeNode.name === "Number") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { type: resolvedType, path } = resolveDotPath(context, dotPos, varTypes);
|
||||||
|
let finalType = resolvedType;
|
||||||
|
if (!finalType) {
|
||||||
|
if (beforeNode.name === "String") finalType = "String";
|
||||||
|
else if (beforeNode.name === "BooleanLiteral") finalType = "Boolean";
|
||||||
|
}
|
||||||
|
let options;
|
||||||
|
if (finalType === "Object") {
|
||||||
|
const rootVarName = path[0];
|
||||||
|
const fieldItems = objectFieldCompletions.get(rootVarName) ?? [];
|
||||||
|
const objMethods = methodsByType["Object"] ?? [];
|
||||||
|
options = [...fieldItems, ...objMethods];
|
||||||
|
} else if (finalType) {
|
||||||
|
options = methodsByType[finalType] ?? allMethods;
|
||||||
|
} else {
|
||||||
|
options = allMethods;
|
||||||
|
}
|
||||||
|
if (options.length === 0) return null;
|
||||||
|
return {
|
||||||
|
from: dotMatch.from + 1,
|
||||||
|
options,
|
||||||
|
validFor: /^\w*$/
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const wordMatch = context.matchBefore(/[a-zA-Z_]\w*/);
|
||||||
|
if (!wordMatch && !context.explicit) return null;
|
||||||
|
if (wordMatch && wordMatch.from === wordMatch.to && !context.explicit)
|
||||||
|
return null;
|
||||||
|
return {
|
||||||
|
from: wordMatch?.from ?? context.pos,
|
||||||
|
options: allIdentifiers,
|
||||||
|
validFor: /^\w*$/
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (0, import_autocomplete.autocompletion)({ override: [completions] });
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/highlight.ts
|
||||||
|
var import_language3 = require("@codemirror/language");
|
||||||
|
var import_highlight2 = require("@lezer/highlight");
|
||||||
|
var dexprHighlightStyle = import_language3.HighlightStyle.define([
|
||||||
|
{ tag: import_highlight2.tags.keyword, color: "#7c3aed" },
|
||||||
|
{ tag: import_highlight2.tags.bool, color: "#d97706" },
|
||||||
|
{ tag: import_highlight2.tags.string, color: "#059669" },
|
||||||
|
{ tag: import_highlight2.tags.number, color: "#2563eb" },
|
||||||
|
{ tag: import_highlight2.tags.lineComment, color: "#9ca3af", fontStyle: "italic" },
|
||||||
|
{ tag: import_highlight2.tags.blockComment, color: "#9ca3af", fontStyle: "italic" },
|
||||||
|
{ tag: import_highlight2.tags.operator, color: "#dc2626" },
|
||||||
|
{ tag: import_highlight2.tags.compareOperator, color: "#dc2626" },
|
||||||
|
{ tag: import_highlight2.tags.variableName, color: "#1f2937" },
|
||||||
|
{ tag: import_highlight2.tags.propertyName, color: "#0891b2" },
|
||||||
|
{ tag: import_highlight2.tags.function(import_highlight2.tags.variableName), color: "#9333ea" },
|
||||||
|
{ tag: import_highlight2.tags.paren, color: "#6b7280" },
|
||||||
|
{ tag: import_highlight2.tags.separator, color: "#6b7280" },
|
||||||
|
{ tag: import_highlight2.tags.derefOperator, color: "#6b7280" }
|
||||||
|
]);
|
||||||
|
function dexprHighlighting2() {
|
||||||
|
return (0, import_language3.syntaxHighlighting)(dexprHighlightStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/index.ts
|
||||||
|
function dexpr(config) {
|
||||||
|
const extensions = [
|
||||||
|
new import_language4.LanguageSupport(dexprLanguage),
|
||||||
|
dexprCompletion(config)
|
||||||
|
];
|
||||||
|
if (config.highlighting !== false) {
|
||||||
|
extensions.push(dexprHighlighting2());
|
||||||
|
}
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
KEYWORDS,
|
||||||
|
dexpr,
|
||||||
|
dexprCompletion,
|
||||||
|
dexprHighlightStyle,
|
||||||
|
dexprHighlighting,
|
||||||
|
dexprLanguage
|
||||||
|
});
|
||||||
61
editor/dist/index.d.cts
vendored
Normal file
61
editor/dist/index.d.cts
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { Extension } from '@codemirror/state';
|
||||||
|
import { Completion } from '@codemirror/autocomplete';
|
||||||
|
import { LRLanguage, HighlightStyle } from '@codemirror/language';
|
||||||
|
|
||||||
|
type DexprType = "String" | "Number" | "Boolean" | "NumberList" | "StringList" | "Object";
|
||||||
|
interface FunctionInfo {
|
||||||
|
name: string;
|
||||||
|
signature: string;
|
||||||
|
doc?: string;
|
||||||
|
}
|
||||||
|
interface MethodInfo {
|
||||||
|
name: string;
|
||||||
|
signature: string;
|
||||||
|
doc?: string;
|
||||||
|
}
|
||||||
|
interface FieldInfo {
|
||||||
|
name: string;
|
||||||
|
type: DexprType;
|
||||||
|
}
|
||||||
|
interface VariableInfo {
|
||||||
|
name: string;
|
||||||
|
type: DexprType;
|
||||||
|
doc?: string;
|
||||||
|
fields?: FieldInfo[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Language metadata — generated by Rust `LanguageInfo::to_json()`,
|
||||||
|
* extended with host-registered functions/methods/variables.
|
||||||
|
*/
|
||||||
|
interface DexprLanguageInfo {
|
||||||
|
functions: FunctionInfo[];
|
||||||
|
methods: Partial<Record<DexprType, MethodInfo[]>>;
|
||||||
|
variables?: VariableInfo[];
|
||||||
|
}
|
||||||
|
declare const KEYWORDS: Completion[];
|
||||||
|
declare function dexprCompletion(info: DexprLanguageInfo): Extension;
|
||||||
|
|
||||||
|
declare const dexprLanguage: LRLanguage;
|
||||||
|
|
||||||
|
declare const dexprHighlightStyle: HighlightStyle;
|
||||||
|
declare function dexprHighlighting(): Extension;
|
||||||
|
|
||||||
|
interface DexprConfig extends DexprLanguageInfo {
|
||||||
|
/** Include default syntax highlighting theme (default: true) */
|
||||||
|
highlighting?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All-in-one dexpr language support for CodeMirror 6.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { dexpr } from "codemirror-lang-dexpr";
|
||||||
|
*
|
||||||
|
* // languageInfo comes from Rust's LanguageInfo::to_json()
|
||||||
|
* // extended with host-registered functions/methods/variables
|
||||||
|
* const extensions = [basicSetup, dexpr(languageInfo)];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function dexpr(config: DexprConfig): Extension;
|
||||||
|
|
||||||
|
export { type DexprConfig, type DexprLanguageInfo, type DexprType, type FieldInfo, type FunctionInfo, KEYWORDS, type MethodInfo, type VariableInfo, dexpr, dexprCompletion, dexprHighlightStyle, dexprHighlighting, dexprLanguage };
|
||||||
61
editor/dist/index.d.ts
vendored
Normal file
61
editor/dist/index.d.ts
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { Extension } from '@codemirror/state';
|
||||||
|
import { Completion } from '@codemirror/autocomplete';
|
||||||
|
import { LRLanguage, HighlightStyle } from '@codemirror/language';
|
||||||
|
|
||||||
|
type DexprType = "String" | "Number" | "Boolean" | "NumberList" | "StringList" | "Object";
|
||||||
|
interface FunctionInfo {
|
||||||
|
name: string;
|
||||||
|
signature: string;
|
||||||
|
doc?: string;
|
||||||
|
}
|
||||||
|
interface MethodInfo {
|
||||||
|
name: string;
|
||||||
|
signature: string;
|
||||||
|
doc?: string;
|
||||||
|
}
|
||||||
|
interface FieldInfo {
|
||||||
|
name: string;
|
||||||
|
type: DexprType;
|
||||||
|
}
|
||||||
|
interface VariableInfo {
|
||||||
|
name: string;
|
||||||
|
type: DexprType;
|
||||||
|
doc?: string;
|
||||||
|
fields?: FieldInfo[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Language metadata — generated by Rust `LanguageInfo::to_json()`,
|
||||||
|
* extended with host-registered functions/methods/variables.
|
||||||
|
*/
|
||||||
|
interface DexprLanguageInfo {
|
||||||
|
functions: FunctionInfo[];
|
||||||
|
methods: Partial<Record<DexprType, MethodInfo[]>>;
|
||||||
|
variables?: VariableInfo[];
|
||||||
|
}
|
||||||
|
declare const KEYWORDS: Completion[];
|
||||||
|
declare function dexprCompletion(info: DexprLanguageInfo): Extension;
|
||||||
|
|
||||||
|
declare const dexprLanguage: LRLanguage;
|
||||||
|
|
||||||
|
declare const dexprHighlightStyle: HighlightStyle;
|
||||||
|
declare function dexprHighlighting(): Extension;
|
||||||
|
|
||||||
|
interface DexprConfig extends DexprLanguageInfo {
|
||||||
|
/** Include default syntax highlighting theme (default: true) */
|
||||||
|
highlighting?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All-in-one dexpr language support for CodeMirror 6.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* import { dexpr } from "codemirror-lang-dexpr";
|
||||||
|
*
|
||||||
|
* // languageInfo comes from Rust's LanguageInfo::to_json()
|
||||||
|
* // extended with host-registered functions/methods/variables
|
||||||
|
* const extensions = [basicSetup, dexpr(languageInfo)];
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare function dexpr(config: DexprConfig): Extension;
|
||||||
|
|
||||||
|
export { type DexprConfig, type DexprLanguageInfo, type DexprType, type FieldInfo, type FunctionInfo, KEYWORDS, type MethodInfo, type VariableInfo, dexpr, dexprCompletion, dexprHighlightStyle, dexprHighlighting, dexprLanguage };
|
||||||
434
editor/dist/index.js
vendored
Normal file
434
editor/dist/index.js
vendored
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
// src/index.ts
|
||||||
|
import { LanguageSupport } from "@codemirror/language";
|
||||||
|
|
||||||
|
// src/language.ts
|
||||||
|
import { LRLanguage } from "@codemirror/language";
|
||||||
|
import { styleTags, tags } from "@lezer/highlight";
|
||||||
|
|
||||||
|
// src/parser.js
|
||||||
|
import { LRParser } from "@lezer/lr";
|
||||||
|
|
||||||
|
// src/tokens.ts
|
||||||
|
import { ExternalTokenizer } from "@lezer/lr";
|
||||||
|
|
||||||
|
// src/parser.terms.js
|
||||||
|
var elseIf = 44;
|
||||||
|
|
||||||
|
// src/tokens.ts
|
||||||
|
var CH_e = 101;
|
||||||
|
var CH_l = 108;
|
||||||
|
var CH_s = 115;
|
||||||
|
var CH_i = 105;
|
||||||
|
var CH_f = 102;
|
||||||
|
var CH_SPACE = 32;
|
||||||
|
var CH_TAB = 9;
|
||||||
|
var CH_NL = 10;
|
||||||
|
var CH_CR = 13;
|
||||||
|
var elseIfTokenizer = new ExternalTokenizer((input) => {
|
||||||
|
if (input.next !== CH_e) return;
|
||||||
|
if (input.peek(1) !== CH_l) return;
|
||||||
|
if (input.peek(2) !== CH_s) return;
|
||||||
|
if (input.peek(3) !== CH_e) return;
|
||||||
|
let pos = 4;
|
||||||
|
const ch = input.peek(pos);
|
||||||
|
if (ch !== CH_SPACE && ch !== CH_TAB && ch !== CH_NL && ch !== CH_CR) return;
|
||||||
|
while (true) {
|
||||||
|
const c = input.peek(pos);
|
||||||
|
if (c === CH_SPACE || c === CH_TAB || c === CH_NL || c === CH_CR) {
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (input.peek(pos) !== CH_i) return;
|
||||||
|
if (input.peek(pos + 1) !== CH_f) return;
|
||||||
|
const after = input.peek(pos + 2);
|
||||||
|
if (after >= 97 && after <= 122 || // a-z
|
||||||
|
after >= 65 && after <= 90 || // A-Z
|
||||||
|
after >= 48 && after <= 57 || // 0-9
|
||||||
|
after === 95)
|
||||||
|
return;
|
||||||
|
input.acceptToken(elseIf, pos + 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// src/parser.js
|
||||||
|
var spec_identifier = { __proto__: null, if: 11, true: 21, false: 21, in: 43, then: 69, else: 71, end: 73 };
|
||||||
|
var parser = LRParser.deserialize({
|
||||||
|
version: 14,
|
||||||
|
states: "+^Q]QQOOOOQP'#Cb'#CbOOQP'#Ce'#CeOwQQO'#CiO`QQO'#CjO#TQRO'#DTO%bQRO'#D_OOQP'#D_'#D_O%iQRO'#D_OOQP'#D]'#D]OOQP'#DU'#DUQ]QQOOOwQQO'#C`O&eQQO,59TO&lQRO'#D_O(zQRO,59UO`QQO,59XO`QQO,59XO`QQO,59XO`QQO,59XO`QQO,59XO)wQQO,59hO)|QQO'#CzOOQP,59i,59iO`QQO,59mOOQP-E7S-E7SO*TQQO,58zOOQP1G.o1G.oO+oQRO1G.sO+vQRO1G.sO-bQRO1G.sO-iQRO1G.sO.[QRO1G.sOOQP'#Cy'#CyOOQP1G/S1G/SO/[QQO'#D`OOQP,59f,59fO/fQQO,59fO/kQRO1G/XO0bQRO1G.fO0oQQO1G/SOOQP7+$i7+$iOwQQO'#DVO1pQQO,59zOOQP1G/Q1G/QO1xQRO7+$QO2TQRO7+$QOwQQO'#DWOOQP7+$Q7+$QO2bQQO7+$QO2iQQO,59qOOQO-E7T-E7TOOQP-E7U-E7UOOQP<<Gl<<GlO2sQQO<<GlO2zQRO<<GlO3VQQO,59rO2sQQO<<GlO3^QQOAN=WOOQPAN=WAN=WO3^QQOAN=WO3eQRO1G/^OOQPG22rG22rO3rQQOG22rO3yQRO7+$xOOQPLD(^LD(^O)wQQO,59hO5RQQO1G.sO5YQQO1G.sO6[QQO1G.sO6cQQO1G.sO6jQQO1G.sO7QQQO,59UOwQQO,59XOwQQO,59XOwQQO,59XOwQQO,59XOwQQO,59XOwQQO'#Cj",
|
||||||
|
stateData: "7n~O!OOSPOSQOS~OT[OVVOWVOYQO[RO_SO`SO!QPO~OVVOWVOYQO[RO_!pO`!pO!QPO~O_cOb`OcaOdbOebOfcOgdOhdOidOjdOleO~OTwXVwXWwXYwX[wX`wX{wX!QwXswXtwX|wX~P!`OvhOT!RXV!RXW!RXY!RX_!RX`!RXb!RXc!RXd!RXe!RXf!RXg!RXh!RXi!RXj!RXl!RX{!RX!Q!RXs!RXt!RX|!RX~O[fO~P#zO[!RX~P#zO_!nOb!kOc!lOd!mOe!mOf!nOg!oOh!oOi!oOj!oOl!dO~OZkO~P%pO[fOZ!RX_!RXb!RXc!RXd!RXe!RXf!RXg!RXh!RXi!RXj!RXl!RXT!RXV!RXW!RXY!RX`!RX{!RX!Q!RXr!RXo!RXs!RXt!RX|!RX~Ob^ac^ad^ae^af^ag^ah^ai^aj^a~O_cOleOT^aV^aW^aY^a[^a`^a{^a!Q^as^at^a|^a~P(]O!QqO~OZtO~PwOrwO~P%pO_cOdbOebOfcOgdOhdOidOjdOleOTaiVaiWaiYai[ai`aibai{ai!Qaisaitai|ai~OcaO~P*[Ocai~P*[O_cOgdOhdOidOjdOleOTaiVaiWaiYai[ai`aibaicaidaieai{ai!Qaisaitai|ai~OfcO~P+}Ofai~P+}Obaicaidaieaifaigaihaiiai~O_cOjdOleOTaiVaiWaiYai[ai`ai{ai!Qaisaitai|ai~P-pOozOZ!SX~P%pOZ|O~OTuiVuiWuiYui[ui`ui{ui!Quisuitui|ui~P!`Os!ROt!QO|!PO~P]O[fOZpi_pibpicpidpiepifpigpihpiipijpilpirpiopi~OozOZ!Sa~Os!WOt!VO|!PO~Os!WOt!VO|!PO~P]Ot!VO~P]OZyaoya~P%pOt!]O~P]Os!^Ot!]O|!PO~Or!_O~P%pOt!`O~P]Oszitzi|zi~P]Ot!cO~P]Oszqtzq|zq~P]O_!nOd!mOe!mOf!nOg!oOh!oOi!oOj!oOl!dOZaibairaioai~Oc!lO~P4WOcai~P4WO_!nOg!oOh!oOi!oOj!oOl!dOZaibaicaidaieairaioai~Of!nO~P5aOfai~P5aO_!nOj!oOl!dOZairaioai~P-pO_!nOl!dOZ^ar^ao^a~P(]OvdjgQPQh~",
|
||||||
|
goto: "'n!TPPPP!UP!dPP#WPPP#W#WPP#WPPPPPPPPP#WP#x$OP$V#WPPP!UP!U$y%e%kPPPP%uP&T'kiXOZw!O!R!W!Z![!^!_!a!bhUOZw!O!R!W!Z![!^!_!a!bu^RS[`abcdfhz!P!k!l!m!n!o!p!_VORSZ[`abcdfhwz!O!P!R!W!Z![!^!_!a!b!k!l!m!n!o!pQreRx!dSgU^RyxtVRS[`abcdfhz!P!k!l!m!n!o!piWOZw!O!R!W!Z![!^!_!a!bQZO[iZ!O!Z![!a!bQ!OwQ!Z!RQ![!WQ!a!^R!b!_Q{sR!T{Q}wS!U}!XR!X!OiYOZw!O!R!W!Z![!^!_!a!bhTOZw!O!R!W!Z![!^!_!a!bQ]RQ_SQj[Ql`QmaQnbQocQpdQsfQvhQ!SzQ!Y!PQ!e!kQ!f!lQ!g!mQ!h!nQ!i!oR!j!pRuf",
|
||||||
|
nodeNames: "\u26A0 LineComment BlockComment Program IfStatement if VariableName Number String BooleanLiteral BooleanLiteral ) ( ParenExpression UnaryExpression - ! BinaryExpression || && CompareOp in + * / % Power MethodCall . PropertyName ArgList , PropertyAccess FunctionCall then else end Assignment AssignOp ExprStatement",
|
||||||
|
maxTerm: 50,
|
||||||
|
nodeProps: [
|
||||||
|
["group", -3, 4, 37, 39, "Statement", -10, 6, 7, 8, 9, 13, 14, 17, 27, 32, 33, "Expression"],
|
||||||
|
["openedBy", 11, "("],
|
||||||
|
["closedBy", 12, ")"]
|
||||||
|
],
|
||||||
|
skippedNodes: [0, 1, 2],
|
||||||
|
repeatNodeCount: 3,
|
||||||
|
tokenData: "+p~RiXY!pYZ!p]^!ppq!pqr#Rrs#`uv%Svw%awx%lxy'Zyz'`z{'e{|'u|}'}}!O(S!O!P([!P!Q(a!Q![*X!^!_*r!_!`*z!`!a*r!c!}+S#R#S+S#T#o+S#p#q+e~!uS!O~XY!pYZ!p]^!ppq!p~#WP`~!_!`#Z~#`Od~~#cWOY#`Zr#`rs#{s#O#`#O#P$Q#P;'S#`;'S;=`$|<%lO#`~$QOW~~$TRO;'S#`;'S;=`$^;=`O#`~$aXOY#`Zr#`rs#{s#O#`#O#P$Q#P;'S#`;'S;=`$|;=`<%l#`<%lO#`~%PP;=`<%l#`~%XPi~!_!`%[~%aOv~~%dPvw%g~%lOc~~%oWOY%lZw%lwx#{x#O%l#O#P&X#P;'S%l;'S;=`'T<%lO%l~&[RO;'S%l;'S;=`&e;=`O%l~&hXOY%lZw%lwx#{x#O%l#O#P&X#P;'S%l;'S;=`'T;=`<%l%l<%lO%l~'WP;=`<%l%l~'`O[~~'eOZ~~'jQg~z{'p!_!`%[~'uOj~~'zPf~!_!`%[~(SOo~~(XP_~!_!`%[~(aOl~~(fRh~z{(o!P!Q)p!_!`%[~(rTOz(oz{)R{;'S(o;'S;=`)j<%lO(o~)UTO!P(o!P!Q)e!Q;'S(o;'S;=`)j<%lO(o~)jOQ~~)mP;=`<%l(o~)uSP~OY)pZ;'S)p;'S;=`*R<%lO)p~*UP;=`<%l)p~*^QV~!O!P*d!Q![*X~*gP!Q![*j~*oPV~!Q![*j~*wPd~!_!`#Z~+PPv~!_!`#Z~+XS!Q~!Q![+S!c!}+S#R#S+S#T#o+S~+hP#p#q+k~+pOb~",
|
||||||
|
tokenizers: [elseIfTokenizer, 0],
|
||||||
|
topRules: { "Program": [0, 3] },
|
||||||
|
specialized: [{ term: 48, get: (value) => spec_identifier[value] || -1 }],
|
||||||
|
tokenPrec: 1033
|
||||||
|
});
|
||||||
|
|
||||||
|
// src/language.ts
|
||||||
|
var dexprHighlighting = styleTags({
|
||||||
|
"if then else end in elseIf": tags.keyword,
|
||||||
|
BooleanLiteral: tags.bool,
|
||||||
|
String: tags.string,
|
||||||
|
Number: tags.number,
|
||||||
|
LineComment: tags.lineComment,
|
||||||
|
BlockComment: tags.blockComment,
|
||||||
|
"CompareOp AssignOp Power": tags.compareOperator,
|
||||||
|
'"+" "-" "*" "/" "%" "!" "||" "&&"': tags.operator,
|
||||||
|
VariableName: tags.variableName,
|
||||||
|
PropertyName: tags.propertyName,
|
||||||
|
"FunctionCall/VariableName": tags.function(tags.variableName),
|
||||||
|
'"(" ")"': tags.paren,
|
||||||
|
'","': tags.separator,
|
||||||
|
'"."': tags.derefOperator
|
||||||
|
});
|
||||||
|
var dexprLanguage = LRLanguage.define({
|
||||||
|
name: "dexpr",
|
||||||
|
parser: parser.configure({
|
||||||
|
props: [dexprHighlighting]
|
||||||
|
}),
|
||||||
|
languageData: {
|
||||||
|
commentTokens: { line: "//", block: { open: "/*", close: "*/" } },
|
||||||
|
closeBrackets: { brackets: ["(", '"', "'"] }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// src/completions.ts
|
||||||
|
import {
|
||||||
|
autocompletion
|
||||||
|
} from "@codemirror/autocomplete";
|
||||||
|
import { syntaxTree } from "@codemirror/language";
|
||||||
|
function funcToCompletion(f) {
|
||||||
|
return {
|
||||||
|
label: f.name,
|
||||||
|
type: "function",
|
||||||
|
detail: f.signature,
|
||||||
|
info: f.doc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function methodToCompletion(m) {
|
||||||
|
return {
|
||||||
|
label: m.name,
|
||||||
|
type: "method",
|
||||||
|
detail: m.signature,
|
||||||
|
info: m.doc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function varToCompletion(v) {
|
||||||
|
return {
|
||||||
|
label: v.name,
|
||||||
|
type: "variable",
|
||||||
|
detail: v.type,
|
||||||
|
info: v.doc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var KEYWORDS = [
|
||||||
|
{ label: "if", type: "keyword" },
|
||||||
|
{ label: "then", type: "keyword" },
|
||||||
|
{ label: "else", type: "keyword" },
|
||||||
|
{ label: "end", type: "keyword" },
|
||||||
|
{ label: "true", type: "keyword", detail: "Boolean" },
|
||||||
|
{ label: "false", type: "keyword", detail: "Boolean" },
|
||||||
|
{ label: "in", type: "keyword", detail: "membership test" }
|
||||||
|
];
|
||||||
|
function inferVariableTypes(context, knownVars) {
|
||||||
|
const types = new Map(knownVars);
|
||||||
|
const tree = syntaxTree(context.state);
|
||||||
|
const doc = context.state.doc;
|
||||||
|
tree.iterate({
|
||||||
|
enter(node) {
|
||||||
|
if (node.name !== "Assignment") return;
|
||||||
|
const varNode = node.node.firstChild;
|
||||||
|
if (!varNode || varNode.name !== "VariableName") return;
|
||||||
|
const varName = doc.sliceString(varNode.from, varNode.to);
|
||||||
|
const assignOp = varNode.nextSibling;
|
||||||
|
if (!assignOp) return;
|
||||||
|
const exprNode = assignOp.nextSibling;
|
||||||
|
if (!exprNode) return;
|
||||||
|
const exprType = inferExprType(exprNode, doc, types);
|
||||||
|
if (exprType) types.set(varName, exprType);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
function inferExprType(node, doc, knownTypes) {
|
||||||
|
switch (node.name) {
|
||||||
|
case "String":
|
||||||
|
return "String";
|
||||||
|
case "Number":
|
||||||
|
return "Number";
|
||||||
|
case "BooleanLiteral":
|
||||||
|
return "Boolean";
|
||||||
|
case "VariableName": {
|
||||||
|
const name = doc.sliceString(node.from, node.to);
|
||||||
|
return knownTypes.get(name) ?? null;
|
||||||
|
}
|
||||||
|
case "MethodCall": {
|
||||||
|
const propNode = findChild(node, "PropertyName");
|
||||||
|
if (!propNode) return null;
|
||||||
|
const method = doc.sliceString(propNode.from, propNode.to);
|
||||||
|
return inferMethodReturnType(method);
|
||||||
|
}
|
||||||
|
case "BinaryExpression": {
|
||||||
|
const first = node.firstChild;
|
||||||
|
if (first) {
|
||||||
|
const t = inferExprType(first, doc, knownTypes);
|
||||||
|
if (t === "String") return "String";
|
||||||
|
if (t === "Number") return "Number";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case "PropertyAccess": {
|
||||||
|
const objNode = node.firstChild;
|
||||||
|
const propNode = findChild(node, "PropertyName");
|
||||||
|
if (!objNode || !propNode) return null;
|
||||||
|
if (objNode.name === "VariableName") {
|
||||||
|
const varName = doc.sliceString(objNode.from, objNode.to);
|
||||||
|
const fieldName = doc.sliceString(propNode.from, propNode.to);
|
||||||
|
const rootType = knownTypes.get(varName);
|
||||||
|
if (rootType === "Object") {
|
||||||
|
return knownTypes.get(`${varName}.${fieldName}`) ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case "FunctionCall":
|
||||||
|
case "ParenExpression":
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function findChild(node, name) {
|
||||||
|
let child = node.firstChild;
|
||||||
|
while (child) {
|
||||||
|
if (child.name === name) return child;
|
||||||
|
child = child.nextSibling;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function inferMethodReturnType(method) {
|
||||||
|
switch (method) {
|
||||||
|
// String -> String
|
||||||
|
case "upper":
|
||||||
|
case "lower":
|
||||||
|
case "trim":
|
||||||
|
case "trimStart":
|
||||||
|
case "trimEnd":
|
||||||
|
case "replace":
|
||||||
|
case "charAt":
|
||||||
|
case "substring":
|
||||||
|
return "String";
|
||||||
|
// String -> Boolean
|
||||||
|
case "contains":
|
||||||
|
case "startsWith":
|
||||||
|
case "endsWith":
|
||||||
|
case "isEmpty":
|
||||||
|
return "Boolean";
|
||||||
|
// String -> Number
|
||||||
|
case "length":
|
||||||
|
case "len":
|
||||||
|
case "indexOf":
|
||||||
|
return "Number";
|
||||||
|
// String -> StringList
|
||||||
|
case "split":
|
||||||
|
return "StringList";
|
||||||
|
// List -> aggregate
|
||||||
|
case "sum":
|
||||||
|
case "avg":
|
||||||
|
case "min":
|
||||||
|
case "max":
|
||||||
|
case "first":
|
||||||
|
case "last":
|
||||||
|
return "Number";
|
||||||
|
// List methods returning lists
|
||||||
|
case "reverse":
|
||||||
|
case "sort":
|
||||||
|
case "slice":
|
||||||
|
return null;
|
||||||
|
// depends on input type
|
||||||
|
case "join":
|
||||||
|
return "String";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function dedup(items) {
|
||||||
|
const seen = /* @__PURE__ */ new Set();
|
||||||
|
return items.filter((item) => {
|
||||||
|
if (seen.has(item.label)) return false;
|
||||||
|
seen.add(item.label);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function dexprCompletion(info) {
|
||||||
|
const functionCompletions = info.functions.map(funcToCompletion);
|
||||||
|
const variableCompletions = (info.variables ?? []).map(varToCompletion);
|
||||||
|
const methodsByType = {};
|
||||||
|
for (const [type, methods] of Object.entries(info.methods)) {
|
||||||
|
methodsByType[type] = (methods ?? []).map(methodToCompletion);
|
||||||
|
}
|
||||||
|
const allMethods = dedup(
|
||||||
|
Object.values(methodsByType).flat()
|
||||||
|
);
|
||||||
|
const allIdentifiers = [
|
||||||
|
...KEYWORDS,
|
||||||
|
...functionCompletions,
|
||||||
|
...variableCompletions
|
||||||
|
];
|
||||||
|
const configVarTypes = /* @__PURE__ */ new Map();
|
||||||
|
for (const v of info.variables ?? []) {
|
||||||
|
configVarTypes.set(v.name, v.type);
|
||||||
|
}
|
||||||
|
const objectFieldCompletions = /* @__PURE__ */ new Map();
|
||||||
|
for (const v of info.variables ?? []) {
|
||||||
|
if (v.type === "Object" && v.fields) {
|
||||||
|
const fieldItems = [];
|
||||||
|
for (const f of v.fields) {
|
||||||
|
configVarTypes.set(`${v.name}.${f.name}`, f.type);
|
||||||
|
fieldItems.push({
|
||||||
|
label: f.name,
|
||||||
|
type: "property",
|
||||||
|
detail: f.type
|
||||||
|
});
|
||||||
|
}
|
||||||
|
objectFieldCompletions.set(v.name, fieldItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function resolveDotPath(context, dotPos, varTypes) {
|
||||||
|
const tree = syntaxTree(context.state);
|
||||||
|
const doc = context.state.doc;
|
||||||
|
const path = [];
|
||||||
|
let pos = dotPos;
|
||||||
|
while (true) {
|
||||||
|
const nodeAtPos = tree.resolveInner(pos, -1);
|
||||||
|
if (nodeAtPos.name === "PropertyName") {
|
||||||
|
path.unshift(doc.sliceString(nodeAtPos.from, nodeAtPos.to));
|
||||||
|
const dotCharPos = nodeAtPos.from - 1;
|
||||||
|
if (dotCharPos >= 0 && doc.sliceString(dotCharPos, dotCharPos + 1) === ".") {
|
||||||
|
pos = dotCharPos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (nodeAtPos.name === "VariableName") {
|
||||||
|
path.unshift(doc.sliceString(nodeAtPos.from, nodeAtPos.to));
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (path.length === 0) return { type: null, path };
|
||||||
|
const rootType = varTypes.get(path[0]) ?? null;
|
||||||
|
if (path.length === 1) return { type: rootType, path };
|
||||||
|
let currentType = rootType;
|
||||||
|
for (let i = 1; i < path.length; i++) {
|
||||||
|
if (currentType !== "Object") {
|
||||||
|
return { type: currentType, path };
|
||||||
|
}
|
||||||
|
const key = `${path[i - 1]}.${path[i]}`;
|
||||||
|
const fieldType = varTypes.get(key) ?? null;
|
||||||
|
currentType = fieldType;
|
||||||
|
}
|
||||||
|
return { type: currentType, path };
|
||||||
|
}
|
||||||
|
function completions(context) {
|
||||||
|
const tree = syntaxTree(context.state);
|
||||||
|
const node = tree.resolveInner(context.pos, -1);
|
||||||
|
if (node.name === "String" || node.name === "LineComment" || node.name === "BlockComment")
|
||||||
|
return null;
|
||||||
|
const dotMatch = context.matchBefore(/\.\w*/);
|
||||||
|
if (dotMatch) {
|
||||||
|
const dotPos = dotMatch.from;
|
||||||
|
const beforeNode = tree.resolveInner(dotPos, -1);
|
||||||
|
const varTypes = inferVariableTypes(context, configVarTypes);
|
||||||
|
if (beforeNode.name === "Number") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { type: resolvedType, path } = resolveDotPath(context, dotPos, varTypes);
|
||||||
|
let finalType = resolvedType;
|
||||||
|
if (!finalType) {
|
||||||
|
if (beforeNode.name === "String") finalType = "String";
|
||||||
|
else if (beforeNode.name === "BooleanLiteral") finalType = "Boolean";
|
||||||
|
}
|
||||||
|
let options;
|
||||||
|
if (finalType === "Object") {
|
||||||
|
const rootVarName = path[0];
|
||||||
|
const fieldItems = objectFieldCompletions.get(rootVarName) ?? [];
|
||||||
|
const objMethods = methodsByType["Object"] ?? [];
|
||||||
|
options = [...fieldItems, ...objMethods];
|
||||||
|
} else if (finalType) {
|
||||||
|
options = methodsByType[finalType] ?? allMethods;
|
||||||
|
} else {
|
||||||
|
options = allMethods;
|
||||||
|
}
|
||||||
|
if (options.length === 0) return null;
|
||||||
|
return {
|
||||||
|
from: dotMatch.from + 1,
|
||||||
|
options,
|
||||||
|
validFor: /^\w*$/
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const wordMatch = context.matchBefore(/[a-zA-Z_]\w*/);
|
||||||
|
if (!wordMatch && !context.explicit) return null;
|
||||||
|
if (wordMatch && wordMatch.from === wordMatch.to && !context.explicit)
|
||||||
|
return null;
|
||||||
|
return {
|
||||||
|
from: wordMatch?.from ?? context.pos,
|
||||||
|
options: allIdentifiers,
|
||||||
|
validFor: /^\w*$/
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return autocompletion({ override: [completions] });
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/highlight.ts
|
||||||
|
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
||||||
|
import { tags as tags2 } from "@lezer/highlight";
|
||||||
|
var dexprHighlightStyle = HighlightStyle.define([
|
||||||
|
{ tag: tags2.keyword, color: "#7c3aed" },
|
||||||
|
{ tag: tags2.bool, color: "#d97706" },
|
||||||
|
{ tag: tags2.string, color: "#059669" },
|
||||||
|
{ tag: tags2.number, color: "#2563eb" },
|
||||||
|
{ tag: tags2.lineComment, color: "#9ca3af", fontStyle: "italic" },
|
||||||
|
{ tag: tags2.blockComment, color: "#9ca3af", fontStyle: "italic" },
|
||||||
|
{ tag: tags2.operator, color: "#dc2626" },
|
||||||
|
{ tag: tags2.compareOperator, color: "#dc2626" },
|
||||||
|
{ tag: tags2.variableName, color: "#1f2937" },
|
||||||
|
{ tag: tags2.propertyName, color: "#0891b2" },
|
||||||
|
{ tag: tags2.function(tags2.variableName), color: "#9333ea" },
|
||||||
|
{ tag: tags2.paren, color: "#6b7280" },
|
||||||
|
{ tag: tags2.separator, color: "#6b7280" },
|
||||||
|
{ tag: tags2.derefOperator, color: "#6b7280" }
|
||||||
|
]);
|
||||||
|
function dexprHighlighting2() {
|
||||||
|
return syntaxHighlighting(dexprHighlightStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/index.ts
|
||||||
|
function dexpr(config) {
|
||||||
|
const extensions = [
|
||||||
|
new LanguageSupport(dexprLanguage),
|
||||||
|
dexprCompletion(config)
|
||||||
|
];
|
||||||
|
if (config.highlighting !== false) {
|
||||||
|
extensions.push(dexprHighlighting2());
|
||||||
|
}
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
KEYWORDS,
|
||||||
|
dexpr,
|
||||||
|
dexprCompletion,
|
||||||
|
dexprHighlightStyle,
|
||||||
|
dexprHighlighting2 as dexprHighlighting,
|
||||||
|
dexprLanguage
|
||||||
|
};
|
||||||
1
editor/node_modules/.bin/acorn
generated
vendored
Symbolic link
1
editor/node_modules/.bin/acorn
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../acorn/bin/acorn
|
||||||
1
editor/node_modules/.bin/esbuild
generated
vendored
Symbolic link
1
editor/node_modules/.bin/esbuild
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../@esbuild/darwin-arm64/bin/esbuild
|
||||||
1
editor/node_modules/.bin/lezer-generator
generated
vendored
Symbolic link
1
editor/node_modules/.bin/lezer-generator
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../@lezer/generator/src/lezer-generator.cjs
|
||||||
1
editor/node_modules/.bin/rollup
generated
vendored
Symbolic link
1
editor/node_modules/.bin/rollup
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../rollup/dist/bin/rollup
|
||||||
1
editor/node_modules/.bin/sucrase
generated
vendored
Symbolic link
1
editor/node_modules/.bin/sucrase
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase
|
||||||
1
editor/node_modules/.bin/sucrase-node
generated
vendored
Symbolic link
1
editor/node_modules/.bin/sucrase-node
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase-node
|
||||||
1
editor/node_modules/.bin/tree-kill
generated
vendored
Symbolic link
1
editor/node_modules/.bin/tree-kill
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../tree-kill/cli.js
|
||||||
1
editor/node_modules/.bin/tsc
generated
vendored
Symbolic link
1
editor/node_modules/.bin/tsc
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../typescript/bin/tsc
|
||||||
1
editor/node_modules/.bin/tsserver
generated
vendored
Symbolic link
1
editor/node_modules/.bin/tsserver
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../typescript/bin/tsserver
|
||||||
1
editor/node_modules/.bin/tsup
generated
vendored
Symbolic link
1
editor/node_modules/.bin/tsup
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../tsup/dist/cli-default.js
|
||||||
1
editor/node_modules/.bin/tsup-node
generated
vendored
Symbolic link
1
editor/node_modules/.bin/tsup-node
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../tsup/dist/cli-node.js
|
||||||
16
editor/node_modules/@codemirror/autocomplete/.github/workflows/dispatch.yml
generated
vendored
Normal file
16
editor/node_modules/@codemirror/autocomplete/.github/workflows/dispatch.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Trigger CI
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Dispatch to main repo
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Emit repository_dispatch
|
||||||
|
uses: mvasigh/dispatch-action@main
|
||||||
|
with:
|
||||||
|
# You should create a personal access token and store it in your repository
|
||||||
|
token: ${{ secrets.DISPATCH_AUTH }}
|
||||||
|
repo: dev
|
||||||
|
owner: codemirror
|
||||||
|
event_type: push
|
||||||
639
editor/node_modules/@codemirror/autocomplete/CHANGELOG.md
generated
vendored
Normal file
639
editor/node_modules/@codemirror/autocomplete/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,639 @@
|
|||||||
|
## 6.20.1 (2026-03-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Clicking the horizontal dots at the top/bottom of a list of completion options now moves the selection there, so that more completions become visible.
|
||||||
|
## 6.20.0 (2025-11-20)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Completions now support a `sortText` property to influence sort order.
|
||||||
|
|
||||||
|
## 6.19.1 (2025-10-23)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure a completion's info panel is associated with that completion in the accessibility tree.
|
||||||
|
|
||||||
|
## 6.19.0 (2025-09-26)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Completion sections may now set their rank to `dynamic` to indicate their order should be determined by the matching score of their best-matching option.
|
||||||
|
|
||||||
|
## 6.18.7 (2025-09-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Add a binding for Alt-i to trigger `startCompletion`, following VS Code's current default bindings.
|
||||||
|
|
||||||
|
Improve handling of nested fields in snippets.
|
||||||
|
|
||||||
|
## 6.18.6 (2025-02-12)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where the closing character for double-angle quotation marks and full-width brackets was computed incorrectly.
|
||||||
|
|
||||||
|
## 6.18.5 (2025-02-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where clicking on the scrollbar for the completion list could move focus out of the editor.
|
||||||
|
|
||||||
|
## 6.18.4 (2024-12-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Align the behavior of snippet completions with text completions in that they overwrite the selected text.
|
||||||
|
|
||||||
|
## 6.18.3 (2024-11-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Backspacing to the start of the completed range will no longer close the completion tooltip when it was triggered implicitly by typing the character before that range.
|
||||||
|
|
||||||
|
## 6.18.2 (2024-10-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't immediately show synchronously updated completions when there are some sources that still need to return.
|
||||||
|
|
||||||
|
## 6.18.1 (2024-09-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where `insertCompletionText` would get confused about the length of the inserted text when it contained CRLF line breaks, and create an invalid selection.
|
||||||
|
|
||||||
|
Add Alt-Backtick as additional binding on macOS, where IME can take over Ctrl-Space.
|
||||||
|
|
||||||
|
## 6.18.0 (2024-08-05)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Style the info element so that newlines are preserved, to make it easier to display multi-line info from a string source.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
When registering an `abort` handler for a completion query, you can now use the `onDocChange` option to indicate that your query should be aborted as soon as the document changes while it is running.
|
||||||
|
|
||||||
|
## 6.17.0 (2024-07-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where completions weren't properly reset when starting a new completion through `activateOnCompletion`.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`CompletionContext` objects now have a `view` property that holds the editor view when the query context has a view available.
|
||||||
|
|
||||||
|
## 6.16.3 (2024-06-19)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Avoid adding an `aria-autocomplete` attribute to the editor when there are no active sources active.
|
||||||
|
|
||||||
|
## 6.16.2 (2024-05-31)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Allow backslash-escaped closing braces inside snippet field names/content.
|
||||||
|
|
||||||
|
## 6.16.1 (2024-05-29)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where multiple backslashes before a brace in a snippet were all removed.
|
||||||
|
|
||||||
|
## 6.16.0 (2024-04-12)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `activateOnCompletion` option allows autocompletion to be configured to chain completion activation for some types of completions.
|
||||||
|
|
||||||
|
## 6.15.0 (2024-03-13)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `filterStrict` option can be used to turn off fuzzy matching of completions.
|
||||||
|
|
||||||
|
## 6.14.0 (2024-03-10)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Completion results can now define a `map` method that can be used to adjust position-dependent information for document changes.
|
||||||
|
|
||||||
|
## 6.13.0 (2024-02-29)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Completions may now provide 'commit characters' that, when typed, commit the completion before inserting the character.
|
||||||
|
|
||||||
|
## 6.12.0 (2024-01-12)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure snippet completions also set `userEvent` to `input.complete`.
|
||||||
|
|
||||||
|
Fix a crash when the editor lost focus during an update and autocompletion was active.
|
||||||
|
|
||||||
|
Fix a crash when using a snippet that has only one field, but multiple instances of that field.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `activateOnTypingDelay` option allows control over the debounce time before the completions are queried when the user types.
|
||||||
|
|
||||||
|
## 6.11.1 (2023-11-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused typing over closed brackets after pressing enter to still not work in many situations.
|
||||||
|
|
||||||
|
## 6.11.0 (2023-11-09)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue that would prevent typing over closed brackets after starting a new line with enter.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Additional elements rendered in completion options with `addToOptions` are now given access to the editor view.
|
||||||
|
|
||||||
|
## 6.10.2 (2023-10-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused `updateSyncTime` to always delay the initial population of the tooltip.
|
||||||
|
|
||||||
|
## 6.10.1 (2023-10-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where picking a selection with the mouse could use the wrong completion if the completion list was updated after being opened.
|
||||||
|
|
||||||
|
## 6.10.0 (2023-10-11)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new autocompletion configuration option `updateSyncTime` allows control over how long fast sources are held back waiting for slower completion sources.
|
||||||
|
|
||||||
|
## 6.9.2 (2023-10-06)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug in `completeAnyWord` that could cause it to generate invalid regular expressions and crash.
|
||||||
|
|
||||||
|
## 6.9.1 (2023-09-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure the cursor is scrolled into view after inserting completion text.
|
||||||
|
|
||||||
|
Make sure scrolling completions into view doesn't get confused when the tooltip is scaled.
|
||||||
|
|
||||||
|
## 6.9.0 (2023-07-18)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Completions may now provide a `displayLabel` property that overrides the way they are displayed in the completion list.
|
||||||
|
|
||||||
|
## 6.8.1 (2023-06-23)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
`acceptCompletion` now returns false (allowing other handlers to take effect) when the completion popup is open but disabled.
|
||||||
|
|
||||||
|
## 6.8.0 (2023-06-12)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The result of `Completion.info` may now include a `destroy` method that will be called when the tooltip is removed.
|
||||||
|
|
||||||
|
## 6.7.1 (2023-05-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that cause incorrect ordering of completions when some results covered input text and others didn't.
|
||||||
|
|
||||||
|
## 6.7.0 (2023-05-11)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `hasNextSnippetField` and `hasPrevSnippetField` functions can be used to figure out if the snippet-field-motion commands apply to a given state.
|
||||||
|
|
||||||
|
## 6.6.1 (2023-05-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that made the editor use the completion's original position, rather than its current position, when changes happened in the document while a result was active.
|
||||||
|
|
||||||
|
## 6.6.0 (2023-04-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug in `insertCompletionText` that caused it to replace the wrong range when a result set's `to` fell after the cursor.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Functions returned by `snippet` can now be called without a completion object.
|
||||||
|
|
||||||
|
## 6.5.1 (2023-04-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Keep completions open when interaction with an info tooltip moves focus out of the editor.
|
||||||
|
|
||||||
|
## 6.5.0 (2023-04-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
When `closeBrackets` skips a bracket, it now generates a change that overwrites the bracket.
|
||||||
|
|
||||||
|
Replace the entire selected range when picking a completion with a non-cursor selection active.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Completions can now provide a `section` field that is used to group them into sections.
|
||||||
|
|
||||||
|
The new `positionInfo` option can be used to provide custom logic for positioning the info tooltips.
|
||||||
|
|
||||||
|
## 6.4.2 (2023-02-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where the apply method created by `snippet` didn't add a `pickedCompletion` annotation to the transactions it created.
|
||||||
|
|
||||||
|
## 6.4.1 (2023-02-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't consider node names in trees that aren't the same language as the one at the completion position in `ifIn` and `ifNotIn`.
|
||||||
|
|
||||||
|
Make sure completions that exactly match the input get a higher score than those that don't (so that even if the latter has a score boost, it ends up lower in the list).
|
||||||
|
|
||||||
|
## 6.4.0 (2022-12-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where the extension would sometimes try to draw a disabled dialog at an outdated position, leading to plugin crashes.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
A `tooltipClass` option to autocompletion can now be used to add additional CSS classes to the completion tooltip.
|
||||||
|
|
||||||
|
## 6.3.4 (2022-11-24)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where completion lists could end up being higher than the tooltip they were in.
|
||||||
|
|
||||||
|
## 6.3.3 (2022-11-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Set an explicit `box-sizing` style on completion icons so CSS resets don't mess them up.
|
||||||
|
|
||||||
|
Allow closing braces in templates to be escaped with a backslash.
|
||||||
|
|
||||||
|
## 6.3.2 (2022-11-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a regression that could cause the completion dialog to stick around when it should be hidden.
|
||||||
|
|
||||||
|
## 6.3.1 (2022-11-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a regression where transactions for picking a completion (without custom `apply` method) no longer had the `pickedCompletion` annotation.
|
||||||
|
|
||||||
|
Reduce flickering for completion sources without `validFor` info by temporarily showing a disabled tooltip while the completion updates.
|
||||||
|
|
||||||
|
Make sure completion info tooltips are kept within the space provided by the `tooltipSpace` option.
|
||||||
|
|
||||||
|
## 6.3.0 (2022-09-22)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Close bracket configuration now supports a `stringPrefixes` property that can be used to allow autoclosing of prefixed strings.
|
||||||
|
|
||||||
|
## 6.2.0 (2022-09-13)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Autocompletion now takes an `interactionDelay` option that can be used to control the delay between the time where completion opens and the time where commands like `acceptCompletion` affect it.
|
||||||
|
|
||||||
|
## 6.1.1 (2022-09-08)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that prevented transactions produced by `deleteBracketPair` from being marked as deletion user events.
|
||||||
|
|
||||||
|
Improve positioning of completion info tooltips so they are less likely to stick out of the screen on small displays.
|
||||||
|
|
||||||
|
## 6.1.0 (2022-07-19)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
You can now provide a `compareCompletions` option to autocompletion to influence the way completions with the same match score are sorted.
|
||||||
|
|
||||||
|
The `selectOnOpen` option to autocompletion can be used to require explicitly selecting a completion option before `acceptCompletion` does anything.
|
||||||
|
|
||||||
|
## 6.0.4 (2022-07-07)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Remove a leftover `console.log` in bracket closing code.
|
||||||
|
|
||||||
|
## 6.0.3 (2022-07-04)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused `closeBrackets` to not close quotes when at the end of a syntactic construct that starts with a similar quote.
|
||||||
|
|
||||||
|
## 6.0.2 (2022-06-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Declare package dependencies as peer dependencies as an attempt to avoid duplicated package issues.
|
||||||
|
|
||||||
|
## 6.0.1 (2022-06-09)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Support escaping `${` or `#{` in snippets.
|
||||||
|
|
||||||
|
## 6.0.0 (2022-06-08)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Scroll the cursor into view when inserting a snippet.
|
||||||
|
|
||||||
|
## 0.20.3 (2022-05-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Add an aria-label to the completion listbox.
|
||||||
|
|
||||||
|
Fix a regression that caused transactions generated for completion to not have a `userEvent` annotation.
|
||||||
|
|
||||||
|
## 0.20.2 (2022-05-24)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now exports an `insertCompletionText` helper that implements the default behavior for applying a completion.
|
||||||
|
|
||||||
|
## 0.20.1 (2022-05-16)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `closeOnBlur` option determines whether the completion tooltip is closed when the editor loses focus.
|
||||||
|
|
||||||
|
`CompletionResult` objects with `filter: false` may now have a `getMatch` property that determines the matched range in the options.
|
||||||
|
|
||||||
|
## 0.20.0 (2022-04-20)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
`CompletionResult.span` has been renamed to `validFor`, and may now hold a function as well as a regular expression.
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Remove code that dropped any options beyond the 300th one when matching and sorting option lists.
|
||||||
|
|
||||||
|
Completion will now apply to all cursors when there are multiple cursors.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`CompletionResult.update` can now be used to implement quick autocompletion updates in a synchronous way.
|
||||||
|
|
||||||
|
The @codemirror/closebrackets package was merged into this one.
|
||||||
|
|
||||||
|
## 0.19.15 (2022-03-23)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `selectedCompletionIndex` function tells you the position of the currently selected completion.
|
||||||
|
|
||||||
|
The new `setSelectionCompletion` function creates a state effect that moves the selected completion to a given index.
|
||||||
|
|
||||||
|
A completion's `info` method may now return null to indicate that no further info is available.
|
||||||
|
|
||||||
|
## 0.19.14 (2022-03-10)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make the ARIA attributes added to the editor during autocompletion spec-compliant.
|
||||||
|
|
||||||
|
## 0.19.13 (2022-02-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where the completion tooltip stayed open if it was explicitly opened and the user backspaced past its start.
|
||||||
|
|
||||||
|
Stop snippet filling when a change happens across one of the snippet fields' boundaries.
|
||||||
|
|
||||||
|
## 0.19.12 (2022-01-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix completion navigation with PageUp/Down when the completion tooltip isn't part of the view DOM.
|
||||||
|
|
||||||
|
## 0.19.11 (2022-01-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused page up/down to only move the selection by two options in the completion tooltip.
|
||||||
|
|
||||||
|
## 0.19.10 (2022-01-05)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure the info tooltip is hidden when the selected option is scrolled out of view.
|
||||||
|
|
||||||
|
Fix a bug in the completion ranking that would sometimes give options that match the input by word start chars higher scores than appropriate.
|
||||||
|
|
||||||
|
Options are now sorted (ascending) by length when their match score is otherwise identical.
|
||||||
|
|
||||||
|
## 0.19.9 (2021-11-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where info tooltips would be visible in an inappropriate position when there was no room to place them properly.
|
||||||
|
|
||||||
|
## 0.19.8 (2021-11-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Give the completion tooltip a minimal width, and show ellipsis when completions overflow the tooltip width.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`autocompletion` now accepts an `aboveCursor` option to make the completion tooltip show up above the cursor.
|
||||||
|
|
||||||
|
## 0.19.7 (2021-11-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make option deduplication less aggressive, so that options with different `type` or `apply` fields don't get merged.
|
||||||
|
|
||||||
|
## 0.19.6 (2021-11-12)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where parsing a snippet with a field that was labeled only by a number crashed.
|
||||||
|
|
||||||
|
## 0.19.5 (2021-11-09)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure info tooltips don't stick out of the bottom of the page.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package exports a new function `selectedCompletion`, which can be used to find out which completion is currently selected.
|
||||||
|
|
||||||
|
Transactions created by picking a completion now have an annotation (`pickedCompletion`) holding the original completion.
|
||||||
|
|
||||||
|
## 0.19.4 (2021-10-24)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't rely on the platform's highlight colors for the active completion, since those are inconsistent and may not be appropriate for the theme.
|
||||||
|
|
||||||
|
Fix incorrect match underline for some kinds of matched completions.
|
||||||
|
|
||||||
|
## 0.19.3 (2021-08-31)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Improve the sorting of completions by using `localeCompare`.
|
||||||
|
|
||||||
|
Fix reading of autocompletions in NVDA screen reader.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `icons` option can be used to turn off icons in the completion list.
|
||||||
|
|
||||||
|
The `optionClass` option can now be used to add CSS classes to the options in the completion list.
|
||||||
|
|
||||||
|
It is now possible to inject additional content into rendered completion options with the `addToOptions` configuration option.
|
||||||
|
|
||||||
|
## 0.19.2 (2021-08-25)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where `completeAnyWord` would return results when there was no query and `explicit` was false.
|
||||||
|
|
||||||
|
## 0.19.1 (2021-08-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix incorrect versions for @lezer dependencies.
|
||||||
|
|
||||||
|
## 0.19.0 (2021-08-11)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 0.19.0
|
||||||
|
|
||||||
|
## 0.18.8 (2021-06-30)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Add an `ifIn` helper function that constrains a completion source to only fire when in a given syntax node. Add support for unfiltered completions
|
||||||
|
|
||||||
|
A completion result can now set a `filter: false` property to disable filtering and sorting of completions, when it already did so itself.
|
||||||
|
|
||||||
|
## 0.18.7 (2021-06-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't treat continued completions when typing after an explicit completion as explicit.
|
||||||
|
|
||||||
|
## 0.18.6 (2021-06-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Adding or reconfiguring completion sources will now cause them to be activated right away if a completion was active.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
You can now specify multiple types in `Completion.type` by separating them by spaces. Small doc comment tweak for Completion.type
|
||||||
|
|
||||||
|
## 0.18.5 (2021-04-23)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a regression where snippet field selection didn't work with @codemirror/state 0.18.6.
|
||||||
|
|
||||||
|
Fix a bug where snippet fields with different position numbers were inappropriately merged.
|
||||||
|
|
||||||
|
## 0.18.4 (2021-04-20)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a crash in Safari when moving the selection during composition.
|
||||||
|
|
||||||
|
## 0.18.3 (2021-03-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Adjust to updated @codemirror/tooltip interface.
|
||||||
|
|
||||||
|
## 0.18.2 (2021-03-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix unintended ES2020 output (the package contains ES6 code again).
|
||||||
|
|
||||||
|
## 0.18.1 (2021-03-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Stop active completion when all sources resolve without producing any matches.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`Completion.info` may now return a promise.
|
||||||
|
|
||||||
|
## 0.18.0 (2021-03-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Only preserve selected option across updates when it isn't the first option.
|
||||||
|
|
||||||
|
## 0.17.4 (2021-01-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a styling issue where the selection had become invisible inside snippet fields (when using `drawSelection`).
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Snippet fields can now be selected with the pointing device (so that they are usable on touch devices).
|
||||||
|
|
||||||
|
## 0.17.3 (2021-01-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where uppercase completions would be incorrectly matched against the typed input.
|
||||||
|
|
||||||
|
## 0.17.2 (2021-01-12)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't bind Cmd-Space on macOS, since that already has a system default binding. Use Ctrl-Space for autocompletion.
|
||||||
|
|
||||||
|
## 0.17.1 (2021-01-06)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now also exports a CommonJS module.
|
||||||
|
|
||||||
|
## 0.17.0 (2020-12-29)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
First numbered release.
|
||||||
|
|
||||||
21
editor/node_modules/@codemirror/autocomplete/LICENSE
generated
vendored
Normal file
21
editor/node_modules/@codemirror/autocomplete/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
43
editor/node_modules/@codemirror/autocomplete/README.md
generated
vendored
Normal file
43
editor/node_modules/@codemirror/autocomplete/README.md
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# @codemirror/autocomplete [](https://www.npmjs.org/package/@codemirror/autocomplete)
|
||||||
|
|
||||||
|
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#autocomplete) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/autocomplete/blob/main/CHANGELOG.md) ]
|
||||||
|
|
||||||
|
This package implements autocompletion for the
|
||||||
|
[CodeMirror](https://codemirror.net/) code editor.
|
||||||
|
|
||||||
|
The [project page](https://codemirror.net/) has more information, a
|
||||||
|
number of [examples](https://codemirror.net/examples/) and the
|
||||||
|
[documentation](https://codemirror.net/docs/).
|
||||||
|
|
||||||
|
This code is released under an
|
||||||
|
[MIT license](https://github.com/codemirror/autocomplete/tree/main/LICENSE).
|
||||||
|
|
||||||
|
We aim to be an inclusive, welcoming community. To make that explicit,
|
||||||
|
we have a [code of
|
||||||
|
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
||||||
|
to communication around the project.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {EditorView} from "@codemirror/view"
|
||||||
|
import {autocompletion} from "@codemirror/autocomplete"
|
||||||
|
import {jsonLanguage} from "@codemirror/lang-json"
|
||||||
|
|
||||||
|
const view = new EditorView({
|
||||||
|
parent: document.body,
|
||||||
|
extensions: [
|
||||||
|
jsonLanguage,
|
||||||
|
autocompletion(),
|
||||||
|
jsonLanguage.data.of({
|
||||||
|
autocomplete: ["id", "name", "address"]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
This configuration will just complete the given words anywhere in JSON
|
||||||
|
context. Most language modules come with more refined autocompletion
|
||||||
|
built-in, but you can also write your own custom autocompletion
|
||||||
|
[sources](https://codemirror.net/docs/ref/#autocomplete.CompletionSource)
|
||||||
|
and associate them with your language this way.
|
||||||
2151
editor/node_modules/@codemirror/autocomplete/dist/index.cjs
generated
vendored
Normal file
2151
editor/node_modules/@codemirror/autocomplete/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
648
editor/node_modules/@codemirror/autocomplete/dist/index.d.cts
generated
vendored
Normal file
648
editor/node_modules/@codemirror/autocomplete/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,648 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { EditorState, ChangeDesc, TransactionSpec, Transaction, StateCommand, Facet, Extension, StateEffect } from '@codemirror/state';
|
||||||
|
import { EditorView, Rect, KeyBinding, Command } from '@codemirror/view';
|
||||||
|
import * as _lezer_common from '@lezer/common';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Objects type used to represent individual completions.
|
||||||
|
*/
|
||||||
|
interface Completion {
|
||||||
|
/**
|
||||||
|
The label to show in the completion picker. This is what input
|
||||||
|
is matched against to determine whether a completion matches (and
|
||||||
|
how well it matches).
|
||||||
|
*/
|
||||||
|
label: string;
|
||||||
|
/**
|
||||||
|
An optional override for the completion's visible label. When
|
||||||
|
using this, matched characters will only be highlighted if you
|
||||||
|
provide a [`getMatch`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.getMatch)
|
||||||
|
function.
|
||||||
|
*/
|
||||||
|
displayLabel?: string;
|
||||||
|
/**
|
||||||
|
Overrides the text that is used to sort completions. Will
|
||||||
|
default to `label` if not given.
|
||||||
|
*/
|
||||||
|
sortText?: string;
|
||||||
|
/**
|
||||||
|
An optional short piece of information to show (with a different
|
||||||
|
style) after the label.
|
||||||
|
*/
|
||||||
|
detail?: string;
|
||||||
|
/**
|
||||||
|
Additional info to show when the completion is selected. Can be
|
||||||
|
a plain string or a function that'll render the DOM structure to
|
||||||
|
show when invoked.
|
||||||
|
*/
|
||||||
|
info?: string | ((completion: Completion) => CompletionInfo | Promise<CompletionInfo>);
|
||||||
|
/**
|
||||||
|
How to apply the completion. The default is to replace it with
|
||||||
|
its [label](https://codemirror.net/6/docs/ref/#autocomplete.Completion.label). When this holds a
|
||||||
|
string, the completion range is replaced by that string. When it
|
||||||
|
is a function, that function is called to perform the
|
||||||
|
completion. If it fires a transaction, it is responsible for
|
||||||
|
adding the [`pickedCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.pickedCompletion)
|
||||||
|
annotation to it.
|
||||||
|
*/
|
||||||
|
apply?: string | ((view: EditorView, completion: Completion, from: number, to: number) => void);
|
||||||
|
/**
|
||||||
|
The type of the completion. This is used to pick an icon to show
|
||||||
|
for the completion. Icons are styled with a CSS class created by
|
||||||
|
appending the type name to `"cm-completionIcon-"`. You can
|
||||||
|
define or restyle icons by defining these selectors. The base
|
||||||
|
library defines simple icons for `class`, `constant`, `enum`,
|
||||||
|
`function`, `interface`, `keyword`, `method`, `namespace`,
|
||||||
|
`property`, `text`, `type`, and `variable`.
|
||||||
|
|
||||||
|
Multiple types can be provided by separating them with spaces.
|
||||||
|
*/
|
||||||
|
type?: string;
|
||||||
|
/**
|
||||||
|
When this option is selected, and one of these characters is
|
||||||
|
typed, insert the completion before typing the character.
|
||||||
|
*/
|
||||||
|
commitCharacters?: readonly string[];
|
||||||
|
/**
|
||||||
|
When given, should be a number from -99 to 99 that adjusts how
|
||||||
|
this completion is ranked compared to other completions that
|
||||||
|
match the input as well as this one. A negative number moves it
|
||||||
|
down the list, a positive number moves it up.
|
||||||
|
*/
|
||||||
|
boost?: number;
|
||||||
|
/**
|
||||||
|
Can be used to divide the completion list into sections.
|
||||||
|
Completions in a given section (matched by name) will be grouped
|
||||||
|
together, with a heading above them. Options without section
|
||||||
|
will appear above all sections. A string value is equivalent to
|
||||||
|
a `{name}` object.
|
||||||
|
*/
|
||||||
|
section?: string | CompletionSection;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
The type returned from
|
||||||
|
[`Completion.info`](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info). May be a DOM
|
||||||
|
node, null to indicate there is no info, or an object with an
|
||||||
|
optional `destroy` method that cleans up the node.
|
||||||
|
*/
|
||||||
|
type CompletionInfo = Node | null | {
|
||||||
|
dom: Node;
|
||||||
|
destroy?(): void;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Object used to describe a completion
|
||||||
|
[section](https://codemirror.net/6/docs/ref/#autocomplete.Completion.section). It is recommended to
|
||||||
|
create a shared object used by all the completions in a given
|
||||||
|
section.
|
||||||
|
*/
|
||||||
|
interface CompletionSection {
|
||||||
|
/**
|
||||||
|
The name of the section. If no `render` method is present, this
|
||||||
|
will be displayed above the options.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
An optional function that renders the section header. Since the
|
||||||
|
headers are shown inside a list, you should make sure the
|
||||||
|
resulting element has a `display: list-item` style.
|
||||||
|
*/
|
||||||
|
header?: (section: CompletionSection) => HTMLElement;
|
||||||
|
/**
|
||||||
|
By default, sections are ordered alphabetically by name. To
|
||||||
|
specify an explicit order, `rank` can be used. Sections with a
|
||||||
|
lower rank will be shown above sections with a higher rank.
|
||||||
|
|
||||||
|
When set to `"dynamic"`, the section's position compared to
|
||||||
|
other dynamic sections depends on the matching score of the
|
||||||
|
best-matching option in the sections.
|
||||||
|
*/
|
||||||
|
rank?: number | "dynamic";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
An instance of this is passed to completion source functions.
|
||||||
|
*/
|
||||||
|
declare class CompletionContext {
|
||||||
|
/**
|
||||||
|
The editor state that the completion happens in.
|
||||||
|
*/
|
||||||
|
readonly state: EditorState;
|
||||||
|
/**
|
||||||
|
The position at which the completion is happening.
|
||||||
|
*/
|
||||||
|
readonly pos: number;
|
||||||
|
/**
|
||||||
|
Indicates whether completion was activated explicitly, or
|
||||||
|
implicitly by typing. The usual way to respond to this is to
|
||||||
|
only return completions when either there is part of a
|
||||||
|
completable entity before the cursor, or `explicit` is true.
|
||||||
|
*/
|
||||||
|
readonly explicit: boolean;
|
||||||
|
/**
|
||||||
|
The editor view. May be undefined if the context was created
|
||||||
|
in a situation where there is no such view available, such as
|
||||||
|
in synchronous updates via
|
||||||
|
[`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
|
||||||
|
or when called by test code.
|
||||||
|
*/
|
||||||
|
readonly view?: EditorView | undefined;
|
||||||
|
/**
|
||||||
|
Create a new completion context. (Mostly useful for testing
|
||||||
|
completion sources—in the editor, the extension will create
|
||||||
|
these for you.)
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
/**
|
||||||
|
The editor state that the completion happens in.
|
||||||
|
*/
|
||||||
|
state: EditorState,
|
||||||
|
/**
|
||||||
|
The position at which the completion is happening.
|
||||||
|
*/
|
||||||
|
pos: number,
|
||||||
|
/**
|
||||||
|
Indicates whether completion was activated explicitly, or
|
||||||
|
implicitly by typing. The usual way to respond to this is to
|
||||||
|
only return completions when either there is part of a
|
||||||
|
completable entity before the cursor, or `explicit` is true.
|
||||||
|
*/
|
||||||
|
explicit: boolean,
|
||||||
|
/**
|
||||||
|
The editor view. May be undefined if the context was created
|
||||||
|
in a situation where there is no such view available, such as
|
||||||
|
in synchronous updates via
|
||||||
|
[`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
|
||||||
|
or when called by test code.
|
||||||
|
*/
|
||||||
|
view?: EditorView | undefined);
|
||||||
|
/**
|
||||||
|
Get the extent, content, and (if there is a token) type of the
|
||||||
|
token before `this.pos`.
|
||||||
|
*/
|
||||||
|
tokenBefore(types: readonly string[]): {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
text: string;
|
||||||
|
type: _lezer_common.NodeType;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
Get the match of the given expression directly before the
|
||||||
|
cursor.
|
||||||
|
*/
|
||||||
|
matchBefore(expr: RegExp): {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
text: string;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
Yields true when the query has been aborted. Can be useful in
|
||||||
|
asynchronous queries to avoid doing work that will be ignored.
|
||||||
|
*/
|
||||||
|
get aborted(): boolean;
|
||||||
|
/**
|
||||||
|
Allows you to register abort handlers, which will be called when
|
||||||
|
the query is
|
||||||
|
[aborted](https://codemirror.net/6/docs/ref/#autocomplete.CompletionContext.aborted).
|
||||||
|
|
||||||
|
By default, running queries will not be aborted for regular
|
||||||
|
typing or backspacing, on the assumption that they are likely to
|
||||||
|
return a result with a
|
||||||
|
[`validFor`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.validFor) field that
|
||||||
|
allows the result to be used after all. Passing `onDocChange:
|
||||||
|
true` will cause this query to be aborted for any document
|
||||||
|
change.
|
||||||
|
*/
|
||||||
|
addEventListener(type: "abort", listener: () => void, options?: {
|
||||||
|
onDocChange: boolean;
|
||||||
|
}): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Given a a fixed array of options, return an autocompleter that
|
||||||
|
completes them.
|
||||||
|
*/
|
||||||
|
declare function completeFromList(list: readonly (string | Completion)[]): CompletionSource;
|
||||||
|
/**
|
||||||
|
Wrap the given completion source so that it will only fire when the
|
||||||
|
cursor is in a syntax node with one of the given names.
|
||||||
|
*/
|
||||||
|
declare function ifIn(nodes: readonly string[], source: CompletionSource): CompletionSource;
|
||||||
|
/**
|
||||||
|
Wrap the given completion source so that it will not fire when the
|
||||||
|
cursor is in a syntax node with one of the given names.
|
||||||
|
*/
|
||||||
|
declare function ifNotIn(nodes: readonly string[], source: CompletionSource): CompletionSource;
|
||||||
|
/**
|
||||||
|
The function signature for a completion source. Such a function
|
||||||
|
may return its [result](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult)
|
||||||
|
synchronously or as a promise. Returning null indicates no
|
||||||
|
completions are available.
|
||||||
|
*/
|
||||||
|
type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
|
||||||
|
/**
|
||||||
|
Interface for objects returned by completion sources.
|
||||||
|
*/
|
||||||
|
interface CompletionResult {
|
||||||
|
/**
|
||||||
|
The start of the range that is being completed.
|
||||||
|
*/
|
||||||
|
from: number;
|
||||||
|
/**
|
||||||
|
The end of the range that is being completed. Defaults to the
|
||||||
|
main cursor position.
|
||||||
|
*/
|
||||||
|
to?: number;
|
||||||
|
/**
|
||||||
|
The completions returned. These don't have to be compared with
|
||||||
|
the input by the source—the autocompletion system will do its
|
||||||
|
own matching (against the text between `from` and `to`) and
|
||||||
|
sorting.
|
||||||
|
*/
|
||||||
|
options: readonly Completion[];
|
||||||
|
/**
|
||||||
|
When given, further typing or deletion that causes the part of
|
||||||
|
the document between ([mapped](https://codemirror.net/6/docs/ref/#state.ChangeDesc.mapPos)) `from`
|
||||||
|
and `to` to match this regular expression or predicate function
|
||||||
|
will not query the completion source again, but continue with
|
||||||
|
this list of options. This can help a lot with responsiveness,
|
||||||
|
since it allows the completion list to be updated synchronously.
|
||||||
|
*/
|
||||||
|
validFor?: RegExp | ((text: string, from: number, to: number, state: EditorState) => boolean);
|
||||||
|
/**
|
||||||
|
By default, the library filters and scores completions. Set
|
||||||
|
`filter` to `false` to disable this, and cause your completions
|
||||||
|
to all be included, in the order they were given. When there are
|
||||||
|
other sources, unfiltered completions appear at the top of the
|
||||||
|
list of completions. `validFor` must not be given when `filter`
|
||||||
|
is `false`, because it only works when filtering.
|
||||||
|
*/
|
||||||
|
filter?: boolean;
|
||||||
|
/**
|
||||||
|
When [`filter`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.filter) is set to
|
||||||
|
`false` or a completion has a
|
||||||
|
[`displayLabel`](https://codemirror.net/6/docs/ref/#autocomplete.Completion.displayLabel), this
|
||||||
|
may be provided to compute the ranges on the label that match
|
||||||
|
the input. Should return an array of numbers where each pair of
|
||||||
|
adjacent numbers provide the start and end of a range. The
|
||||||
|
second argument, the match found by the library, is only passed
|
||||||
|
when `filter` isn't `false`.
|
||||||
|
*/
|
||||||
|
getMatch?: (completion: Completion, matched?: readonly number[]) => readonly number[];
|
||||||
|
/**
|
||||||
|
Synchronously update the completion result after typing or
|
||||||
|
deletion. If given, this should not do any expensive work, since
|
||||||
|
it will be called during editor state updates. The function
|
||||||
|
should make sure (similar to
|
||||||
|
[`validFor`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.validFor)) that the
|
||||||
|
completion still applies in the new state.
|
||||||
|
*/
|
||||||
|
update?: (current: CompletionResult, from: number, to: number, context: CompletionContext) => CompletionResult | null;
|
||||||
|
/**
|
||||||
|
When results contain position-dependent information in, for
|
||||||
|
example, `apply` methods, you can provide this method to update
|
||||||
|
the result for transactions that happen after the query. It is
|
||||||
|
not necessary to update `from` and `to`—those are tracked
|
||||||
|
automatically.
|
||||||
|
*/
|
||||||
|
map?: (current: CompletionResult, changes: ChangeDesc) => CompletionResult | null;
|
||||||
|
/**
|
||||||
|
Set a default set of [commit
|
||||||
|
characters](https://codemirror.net/6/docs/ref/#autocomplete.Completion.commitCharacters) for all
|
||||||
|
options in this result.
|
||||||
|
*/
|
||||||
|
commitCharacters?: readonly string[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
This annotation is added to transactions that are produced by
|
||||||
|
picking a completion.
|
||||||
|
*/
|
||||||
|
declare const pickedCompletion: _codemirror_state.AnnotationType<Completion>;
|
||||||
|
/**
|
||||||
|
Helper function that returns a transaction spec which inserts a
|
||||||
|
completion's text in the main selection range, and any other
|
||||||
|
selection range that has the same text in front of it.
|
||||||
|
*/
|
||||||
|
declare function insertCompletionText(state: EditorState, text: string, from: number, to: number): TransactionSpec;
|
||||||
|
|
||||||
|
interface CompletionConfig {
|
||||||
|
/**
|
||||||
|
When enabled (defaults to true), autocompletion will start
|
||||||
|
whenever the user types something that can be completed.
|
||||||
|
*/
|
||||||
|
activateOnTyping?: boolean;
|
||||||
|
/**
|
||||||
|
When given, if a completion that matches the predicate is
|
||||||
|
picked, reactivate completion again as if it was typed normally.
|
||||||
|
*/
|
||||||
|
activateOnCompletion?: (completion: Completion) => boolean;
|
||||||
|
/**
|
||||||
|
The amount of time to wait for further typing before querying
|
||||||
|
completion sources via
|
||||||
|
[`activateOnTyping`](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion^config.activateOnTyping).
|
||||||
|
Defaults to 100, which should be fine unless your completion
|
||||||
|
source is very slow and/or doesn't use `validFor`.
|
||||||
|
*/
|
||||||
|
activateOnTypingDelay?: number;
|
||||||
|
/**
|
||||||
|
By default, when completion opens, the first option is selected
|
||||||
|
and can be confirmed with
|
||||||
|
[`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion). When this
|
||||||
|
is set to false, the completion widget starts with no completion
|
||||||
|
selected, and the user has to explicitly move to a completion
|
||||||
|
before you can confirm one.
|
||||||
|
*/
|
||||||
|
selectOnOpen?: boolean;
|
||||||
|
/**
|
||||||
|
Override the completion sources used. By default, they will be
|
||||||
|
taken from the `"autocomplete"` [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) (which should hold
|
||||||
|
[completion sources](https://codemirror.net/6/docs/ref/#autocomplete.CompletionSource) or arrays
|
||||||
|
of [completions](https://codemirror.net/6/docs/ref/#autocomplete.Completion)).
|
||||||
|
*/
|
||||||
|
override?: readonly CompletionSource[] | null;
|
||||||
|
/**
|
||||||
|
Determines whether the completion tooltip is closed when the
|
||||||
|
editor loses focus. Defaults to true.
|
||||||
|
*/
|
||||||
|
closeOnBlur?: boolean;
|
||||||
|
/**
|
||||||
|
The maximum number of options to render to the DOM.
|
||||||
|
*/
|
||||||
|
maxRenderedOptions?: number;
|
||||||
|
/**
|
||||||
|
Set this to false to disable the [default completion
|
||||||
|
keymap](https://codemirror.net/6/docs/ref/#autocomplete.completionKeymap). (This requires you to
|
||||||
|
add bindings to control completion yourself. The bindings should
|
||||||
|
probably have a higher precedence than other bindings for the
|
||||||
|
same keys.)
|
||||||
|
*/
|
||||||
|
defaultKeymap?: boolean;
|
||||||
|
/**
|
||||||
|
By default, completions are shown below the cursor when there is
|
||||||
|
space. Setting this to true will make the extension put the
|
||||||
|
completions above the cursor when possible.
|
||||||
|
*/
|
||||||
|
aboveCursor?: boolean;
|
||||||
|
/**
|
||||||
|
When given, this may return an additional CSS class to add to
|
||||||
|
the completion dialog element.
|
||||||
|
*/
|
||||||
|
tooltipClass?: (state: EditorState) => string;
|
||||||
|
/**
|
||||||
|
This can be used to add additional CSS classes to completion
|
||||||
|
options.
|
||||||
|
*/
|
||||||
|
optionClass?: (completion: Completion) => string;
|
||||||
|
/**
|
||||||
|
By default, the library will render icons based on the
|
||||||
|
completion's [type](https://codemirror.net/6/docs/ref/#autocomplete.Completion.type) in front of
|
||||||
|
each option. Set this to false to turn that off.
|
||||||
|
*/
|
||||||
|
icons?: boolean;
|
||||||
|
/**
|
||||||
|
This option can be used to inject additional content into
|
||||||
|
options. The `render` function will be called for each visible
|
||||||
|
completion, and should produce a DOM node to show. `position`
|
||||||
|
determines where in the DOM the result appears, relative to
|
||||||
|
other added widgets and the standard content. The default icons
|
||||||
|
have position 20, the label position 50, and the detail position
|
||||||
|
80.
|
||||||
|
*/
|
||||||
|
addToOptions?: {
|
||||||
|
render: (completion: Completion, state: EditorState, view: EditorView) => Node | null;
|
||||||
|
position: number;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
By default, [info](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info) tooltips are
|
||||||
|
placed to the side of the selected completion. This option can
|
||||||
|
be used to override that. It will be given rectangles for the
|
||||||
|
list of completions, the selected option, the info element, and
|
||||||
|
the availble [tooltip
|
||||||
|
space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace), and should return
|
||||||
|
style and/or class strings for the info element.
|
||||||
|
*/
|
||||||
|
positionInfo?: (view: EditorView, list: Rect, option: Rect, info: Rect, space: Rect) => {
|
||||||
|
style?: string;
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
The comparison function to use when sorting completions with the same
|
||||||
|
match score. Defaults to using
|
||||||
|
[`localeCompare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare).
|
||||||
|
*/
|
||||||
|
compareCompletions?: (a: Completion, b: Completion) => number;
|
||||||
|
/**
|
||||||
|
When set to true (the default is false), turn off fuzzy matching
|
||||||
|
of completions and only show those that start with the text the
|
||||||
|
user typed. Only takes effect for results where
|
||||||
|
[`filter`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.filter) isn't false.
|
||||||
|
*/
|
||||||
|
filterStrict?: boolean;
|
||||||
|
/**
|
||||||
|
By default, commands relating to an open completion only take
|
||||||
|
effect 75 milliseconds after the completion opened, so that key
|
||||||
|
presses made before the user is aware of the tooltip don't go to
|
||||||
|
the tooltip. This option can be used to configure that delay.
|
||||||
|
*/
|
||||||
|
interactionDelay?: number;
|
||||||
|
/**
|
||||||
|
When there are multiple asynchronous completion sources, this
|
||||||
|
controls how long the extension waits for a slow source before
|
||||||
|
displaying results from faster sources. Defaults to 100
|
||||||
|
milliseconds.
|
||||||
|
*/
|
||||||
|
updateSyncTime?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert a snippet template to a function that can
|
||||||
|
[apply](https://codemirror.net/6/docs/ref/#autocomplete.Completion.apply) it. Snippets are written
|
||||||
|
using syntax like this:
|
||||||
|
|
||||||
|
"for (let ${index} = 0; ${index} < ${end}; ${index}++) {\n\t${}\n}"
|
||||||
|
|
||||||
|
Each `${}` placeholder (you may also use `#{}`) indicates a field
|
||||||
|
that the user can fill in. Its name, if any, will be the default
|
||||||
|
content for the field.
|
||||||
|
|
||||||
|
When the snippet is activated by calling the returned function,
|
||||||
|
the code is inserted at the given position. Newlines in the
|
||||||
|
template are indented by the indentation of the start line, plus
|
||||||
|
one [indent unit](https://codemirror.net/6/docs/ref/#language.indentUnit) per tab character after
|
||||||
|
the newline.
|
||||||
|
|
||||||
|
On activation, (all instances of) the first field are selected.
|
||||||
|
The user can move between fields with Tab and Shift-Tab as long as
|
||||||
|
the fields are active. Moving to the last field or moving the
|
||||||
|
cursor out of the current field deactivates the fields.
|
||||||
|
|
||||||
|
The order of fields defaults to textual order, but you can add
|
||||||
|
numbers to placeholders (`${1}` or `${1:defaultText}`) to provide
|
||||||
|
a custom order.
|
||||||
|
|
||||||
|
To include a literal `{` or `}` in your template, put a backslash
|
||||||
|
in front of it. This will be removed and the brace will not be
|
||||||
|
interpreted as indicating a placeholder.
|
||||||
|
*/
|
||||||
|
declare function snippet(template: string): (editor: {
|
||||||
|
state: EditorState;
|
||||||
|
dispatch: (tr: Transaction) => void;
|
||||||
|
}, completion: Completion | null, from: number, to: number) => void;
|
||||||
|
/**
|
||||||
|
A command that clears the active snippet, if any.
|
||||||
|
*/
|
||||||
|
declare const clearSnippet: StateCommand;
|
||||||
|
/**
|
||||||
|
Move to the next snippet field, if available.
|
||||||
|
*/
|
||||||
|
declare const nextSnippetField: StateCommand;
|
||||||
|
/**
|
||||||
|
Move to the previous snippet field, if available.
|
||||||
|
*/
|
||||||
|
declare const prevSnippetField: StateCommand;
|
||||||
|
/**
|
||||||
|
Check if there is an active snippet with a next field for
|
||||||
|
`nextSnippetField` to move to.
|
||||||
|
*/
|
||||||
|
declare function hasNextSnippetField(state: EditorState): boolean;
|
||||||
|
/**
|
||||||
|
Returns true if there is an active snippet and a previous field
|
||||||
|
for `prevSnippetField` to move to.
|
||||||
|
*/
|
||||||
|
declare function hasPrevSnippetField(state: EditorState): boolean;
|
||||||
|
/**
|
||||||
|
A facet that can be used to configure the key bindings used by
|
||||||
|
snippets. The default binds Tab to
|
||||||
|
[`nextSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.nextSnippetField), Shift-Tab to
|
||||||
|
[`prevSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.prevSnippetField), and Escape
|
||||||
|
to [`clearSnippet`](https://codemirror.net/6/docs/ref/#autocomplete.clearSnippet).
|
||||||
|
*/
|
||||||
|
declare const snippetKeymap: Facet<readonly KeyBinding[], readonly KeyBinding[]>;
|
||||||
|
/**
|
||||||
|
Create a completion from a snippet. Returns an object with the
|
||||||
|
properties from `completion`, plus an `apply` function that
|
||||||
|
applies the snippet.
|
||||||
|
*/
|
||||||
|
declare function snippetCompletion(template: string, completion: Completion): Completion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a command that moves the completion selection forward or
|
||||||
|
backward by the given amount.
|
||||||
|
*/
|
||||||
|
declare function moveCompletionSelection(forward: boolean, by?: "option" | "page"): Command;
|
||||||
|
/**
|
||||||
|
Accept the current completion.
|
||||||
|
*/
|
||||||
|
declare const acceptCompletion: Command;
|
||||||
|
/**
|
||||||
|
Explicitly start autocompletion.
|
||||||
|
*/
|
||||||
|
declare const startCompletion: Command;
|
||||||
|
/**
|
||||||
|
Close the currently active completion.
|
||||||
|
*/
|
||||||
|
declare const closeCompletion: Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
A completion source that will scan the document for words (using a
|
||||||
|
[character categorizer](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer)), and
|
||||||
|
return those as completions.
|
||||||
|
*/
|
||||||
|
declare const completeAnyWord: CompletionSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Configures bracket closing behavior for a syntax (via
|
||||||
|
[language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt)) using the `"closeBrackets"`
|
||||||
|
identifier.
|
||||||
|
*/
|
||||||
|
interface CloseBracketConfig {
|
||||||
|
/**
|
||||||
|
The opening brackets to close. Defaults to `["(", "[", "{", "'",
|
||||||
|
'"']`. Brackets may be single characters or a triple of quotes
|
||||||
|
(as in `"'''"`).
|
||||||
|
*/
|
||||||
|
brackets?: string[];
|
||||||
|
/**
|
||||||
|
Characters in front of which newly opened brackets are
|
||||||
|
automatically closed. Closing always happens in front of
|
||||||
|
whitespace. Defaults to `")]}:;>"`.
|
||||||
|
*/
|
||||||
|
before?: string;
|
||||||
|
/**
|
||||||
|
When determining whether a given node may be a string, recognize
|
||||||
|
these prefixes before the opening quote.
|
||||||
|
*/
|
||||||
|
stringPrefixes?: string[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Extension to enable bracket-closing behavior. When a closeable
|
||||||
|
bracket is typed, its closing bracket is immediately inserted
|
||||||
|
after the cursor. When closing a bracket directly in front of a
|
||||||
|
closing bracket inserted by the extension, the cursor moves over
|
||||||
|
that bracket.
|
||||||
|
*/
|
||||||
|
declare function closeBrackets(): Extension;
|
||||||
|
/**
|
||||||
|
Command that implements deleting a pair of matching brackets when
|
||||||
|
the cursor is between them.
|
||||||
|
*/
|
||||||
|
declare const deleteBracketPair: StateCommand;
|
||||||
|
/**
|
||||||
|
Close-brackets related key bindings. Binds Backspace to
|
||||||
|
[`deleteBracketPair`](https://codemirror.net/6/docs/ref/#autocomplete.deleteBracketPair).
|
||||||
|
*/
|
||||||
|
declare const closeBracketsKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
Implements the extension's behavior on text insertion. If the
|
||||||
|
given string counts as a bracket in the language around the
|
||||||
|
selection, and replacing the selection with it requires custom
|
||||||
|
behavior (inserting a closing version or skipping past a
|
||||||
|
previously-closed bracket), this function returns a transaction
|
||||||
|
representing that custom behavior. (You only need this if you want
|
||||||
|
to programmatically insert brackets—the
|
||||||
|
[`closeBrackets`](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets) extension will
|
||||||
|
take care of running this for user input.)
|
||||||
|
*/
|
||||||
|
declare function insertBracket(state: EditorState, bracket: string): Transaction | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an extension that enables autocompletion.
|
||||||
|
*/
|
||||||
|
declare function autocompletion(config?: CompletionConfig): Extension;
|
||||||
|
/**
|
||||||
|
Basic keybindings for autocompletion.
|
||||||
|
|
||||||
|
- Ctrl-Space (and Alt-\` or Alt-i on macOS): [`startCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.startCompletion)
|
||||||
|
- Escape: [`closeCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.closeCompletion)
|
||||||
|
- ArrowDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true)`
|
||||||
|
- ArrowUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false)`
|
||||||
|
- PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")`
|
||||||
|
- PageUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false, "page")`
|
||||||
|
- Enter: [`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion)
|
||||||
|
*/
|
||||||
|
declare const completionKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
Get the current completion status. When completions are available,
|
||||||
|
this will return `"active"`. When completions are pending (in the
|
||||||
|
process of being queried), this returns `"pending"`. Otherwise, it
|
||||||
|
returns `null`.
|
||||||
|
*/
|
||||||
|
declare function completionStatus(state: EditorState): null | "active" | "pending";
|
||||||
|
/**
|
||||||
|
Returns the available completions as an array.
|
||||||
|
*/
|
||||||
|
declare function currentCompletions(state: EditorState): readonly Completion[];
|
||||||
|
/**
|
||||||
|
Return the currently selected completion, if any.
|
||||||
|
*/
|
||||||
|
declare function selectedCompletion(state: EditorState): Completion | null;
|
||||||
|
/**
|
||||||
|
Returns the currently selected position in the active completion
|
||||||
|
list, or null if no completions are active.
|
||||||
|
*/
|
||||||
|
declare function selectedCompletionIndex(state: EditorState): number | null;
|
||||||
|
/**
|
||||||
|
Create an effect that can be attached to a transaction to change
|
||||||
|
the currently selected completion.
|
||||||
|
*/
|
||||||
|
declare function setSelectedCompletion(index: number): StateEffect<unknown>;
|
||||||
|
|
||||||
|
export { type CloseBracketConfig, type Completion, CompletionContext, type CompletionInfo, type CompletionResult, type CompletionSection, type CompletionSource, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, hasNextSnippetField, hasPrevSnippetField, ifIn, ifNotIn, insertBracket, insertCompletionText, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
|
||||||
648
editor/node_modules/@codemirror/autocomplete/dist/index.d.ts
generated
vendored
Normal file
648
editor/node_modules/@codemirror/autocomplete/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,648 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { EditorState, ChangeDesc, TransactionSpec, Transaction, StateCommand, Facet, Extension, StateEffect } from '@codemirror/state';
|
||||||
|
import { EditorView, Rect, KeyBinding, Command } from '@codemirror/view';
|
||||||
|
import * as _lezer_common from '@lezer/common';
|
||||||
|
|
||||||
|
/**
|
||||||
|
Objects type used to represent individual completions.
|
||||||
|
*/
|
||||||
|
interface Completion {
|
||||||
|
/**
|
||||||
|
The label to show in the completion picker. This is what input
|
||||||
|
is matched against to determine whether a completion matches (and
|
||||||
|
how well it matches).
|
||||||
|
*/
|
||||||
|
label: string;
|
||||||
|
/**
|
||||||
|
An optional override for the completion's visible label. When
|
||||||
|
using this, matched characters will only be highlighted if you
|
||||||
|
provide a [`getMatch`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.getMatch)
|
||||||
|
function.
|
||||||
|
*/
|
||||||
|
displayLabel?: string;
|
||||||
|
/**
|
||||||
|
Overrides the text that is used to sort completions. Will
|
||||||
|
default to `label` if not given.
|
||||||
|
*/
|
||||||
|
sortText?: string;
|
||||||
|
/**
|
||||||
|
An optional short piece of information to show (with a different
|
||||||
|
style) after the label.
|
||||||
|
*/
|
||||||
|
detail?: string;
|
||||||
|
/**
|
||||||
|
Additional info to show when the completion is selected. Can be
|
||||||
|
a plain string or a function that'll render the DOM structure to
|
||||||
|
show when invoked.
|
||||||
|
*/
|
||||||
|
info?: string | ((completion: Completion) => CompletionInfo | Promise<CompletionInfo>);
|
||||||
|
/**
|
||||||
|
How to apply the completion. The default is to replace it with
|
||||||
|
its [label](https://codemirror.net/6/docs/ref/#autocomplete.Completion.label). When this holds a
|
||||||
|
string, the completion range is replaced by that string. When it
|
||||||
|
is a function, that function is called to perform the
|
||||||
|
completion. If it fires a transaction, it is responsible for
|
||||||
|
adding the [`pickedCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.pickedCompletion)
|
||||||
|
annotation to it.
|
||||||
|
*/
|
||||||
|
apply?: string | ((view: EditorView, completion: Completion, from: number, to: number) => void);
|
||||||
|
/**
|
||||||
|
The type of the completion. This is used to pick an icon to show
|
||||||
|
for the completion. Icons are styled with a CSS class created by
|
||||||
|
appending the type name to `"cm-completionIcon-"`. You can
|
||||||
|
define or restyle icons by defining these selectors. The base
|
||||||
|
library defines simple icons for `class`, `constant`, `enum`,
|
||||||
|
`function`, `interface`, `keyword`, `method`, `namespace`,
|
||||||
|
`property`, `text`, `type`, and `variable`.
|
||||||
|
|
||||||
|
Multiple types can be provided by separating them with spaces.
|
||||||
|
*/
|
||||||
|
type?: string;
|
||||||
|
/**
|
||||||
|
When this option is selected, and one of these characters is
|
||||||
|
typed, insert the completion before typing the character.
|
||||||
|
*/
|
||||||
|
commitCharacters?: readonly string[];
|
||||||
|
/**
|
||||||
|
When given, should be a number from -99 to 99 that adjusts how
|
||||||
|
this completion is ranked compared to other completions that
|
||||||
|
match the input as well as this one. A negative number moves it
|
||||||
|
down the list, a positive number moves it up.
|
||||||
|
*/
|
||||||
|
boost?: number;
|
||||||
|
/**
|
||||||
|
Can be used to divide the completion list into sections.
|
||||||
|
Completions in a given section (matched by name) will be grouped
|
||||||
|
together, with a heading above them. Options without section
|
||||||
|
will appear above all sections. A string value is equivalent to
|
||||||
|
a `{name}` object.
|
||||||
|
*/
|
||||||
|
section?: string | CompletionSection;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
The type returned from
|
||||||
|
[`Completion.info`](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info). May be a DOM
|
||||||
|
node, null to indicate there is no info, or an object with an
|
||||||
|
optional `destroy` method that cleans up the node.
|
||||||
|
*/
|
||||||
|
type CompletionInfo = Node | null | {
|
||||||
|
dom: Node;
|
||||||
|
destroy?(): void;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Object used to describe a completion
|
||||||
|
[section](https://codemirror.net/6/docs/ref/#autocomplete.Completion.section). It is recommended to
|
||||||
|
create a shared object used by all the completions in a given
|
||||||
|
section.
|
||||||
|
*/
|
||||||
|
interface CompletionSection {
|
||||||
|
/**
|
||||||
|
The name of the section. If no `render` method is present, this
|
||||||
|
will be displayed above the options.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
An optional function that renders the section header. Since the
|
||||||
|
headers are shown inside a list, you should make sure the
|
||||||
|
resulting element has a `display: list-item` style.
|
||||||
|
*/
|
||||||
|
header?: (section: CompletionSection) => HTMLElement;
|
||||||
|
/**
|
||||||
|
By default, sections are ordered alphabetically by name. To
|
||||||
|
specify an explicit order, `rank` can be used. Sections with a
|
||||||
|
lower rank will be shown above sections with a higher rank.
|
||||||
|
|
||||||
|
When set to `"dynamic"`, the section's position compared to
|
||||||
|
other dynamic sections depends on the matching score of the
|
||||||
|
best-matching option in the sections.
|
||||||
|
*/
|
||||||
|
rank?: number | "dynamic";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
An instance of this is passed to completion source functions.
|
||||||
|
*/
|
||||||
|
declare class CompletionContext {
|
||||||
|
/**
|
||||||
|
The editor state that the completion happens in.
|
||||||
|
*/
|
||||||
|
readonly state: EditorState;
|
||||||
|
/**
|
||||||
|
The position at which the completion is happening.
|
||||||
|
*/
|
||||||
|
readonly pos: number;
|
||||||
|
/**
|
||||||
|
Indicates whether completion was activated explicitly, or
|
||||||
|
implicitly by typing. The usual way to respond to this is to
|
||||||
|
only return completions when either there is part of a
|
||||||
|
completable entity before the cursor, or `explicit` is true.
|
||||||
|
*/
|
||||||
|
readonly explicit: boolean;
|
||||||
|
/**
|
||||||
|
The editor view. May be undefined if the context was created
|
||||||
|
in a situation where there is no such view available, such as
|
||||||
|
in synchronous updates via
|
||||||
|
[`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
|
||||||
|
or when called by test code.
|
||||||
|
*/
|
||||||
|
readonly view?: EditorView | undefined;
|
||||||
|
/**
|
||||||
|
Create a new completion context. (Mostly useful for testing
|
||||||
|
completion sources—in the editor, the extension will create
|
||||||
|
these for you.)
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
/**
|
||||||
|
The editor state that the completion happens in.
|
||||||
|
*/
|
||||||
|
state: EditorState,
|
||||||
|
/**
|
||||||
|
The position at which the completion is happening.
|
||||||
|
*/
|
||||||
|
pos: number,
|
||||||
|
/**
|
||||||
|
Indicates whether completion was activated explicitly, or
|
||||||
|
implicitly by typing. The usual way to respond to this is to
|
||||||
|
only return completions when either there is part of a
|
||||||
|
completable entity before the cursor, or `explicit` is true.
|
||||||
|
*/
|
||||||
|
explicit: boolean,
|
||||||
|
/**
|
||||||
|
The editor view. May be undefined if the context was created
|
||||||
|
in a situation where there is no such view available, such as
|
||||||
|
in synchronous updates via
|
||||||
|
[`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
|
||||||
|
or when called by test code.
|
||||||
|
*/
|
||||||
|
view?: EditorView | undefined);
|
||||||
|
/**
|
||||||
|
Get the extent, content, and (if there is a token) type of the
|
||||||
|
token before `this.pos`.
|
||||||
|
*/
|
||||||
|
tokenBefore(types: readonly string[]): {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
text: string;
|
||||||
|
type: _lezer_common.NodeType;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
Get the match of the given expression directly before the
|
||||||
|
cursor.
|
||||||
|
*/
|
||||||
|
matchBefore(expr: RegExp): {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
text: string;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
Yields true when the query has been aborted. Can be useful in
|
||||||
|
asynchronous queries to avoid doing work that will be ignored.
|
||||||
|
*/
|
||||||
|
get aborted(): boolean;
|
||||||
|
/**
|
||||||
|
Allows you to register abort handlers, which will be called when
|
||||||
|
the query is
|
||||||
|
[aborted](https://codemirror.net/6/docs/ref/#autocomplete.CompletionContext.aborted).
|
||||||
|
|
||||||
|
By default, running queries will not be aborted for regular
|
||||||
|
typing or backspacing, on the assumption that they are likely to
|
||||||
|
return a result with a
|
||||||
|
[`validFor`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.validFor) field that
|
||||||
|
allows the result to be used after all. Passing `onDocChange:
|
||||||
|
true` will cause this query to be aborted for any document
|
||||||
|
change.
|
||||||
|
*/
|
||||||
|
addEventListener(type: "abort", listener: () => void, options?: {
|
||||||
|
onDocChange: boolean;
|
||||||
|
}): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Given a a fixed array of options, return an autocompleter that
|
||||||
|
completes them.
|
||||||
|
*/
|
||||||
|
declare function completeFromList(list: readonly (string | Completion)[]): CompletionSource;
|
||||||
|
/**
|
||||||
|
Wrap the given completion source so that it will only fire when the
|
||||||
|
cursor is in a syntax node with one of the given names.
|
||||||
|
*/
|
||||||
|
declare function ifIn(nodes: readonly string[], source: CompletionSource): CompletionSource;
|
||||||
|
/**
|
||||||
|
Wrap the given completion source so that it will not fire when the
|
||||||
|
cursor is in a syntax node with one of the given names.
|
||||||
|
*/
|
||||||
|
declare function ifNotIn(nodes: readonly string[], source: CompletionSource): CompletionSource;
|
||||||
|
/**
|
||||||
|
The function signature for a completion source. Such a function
|
||||||
|
may return its [result](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult)
|
||||||
|
synchronously or as a promise. Returning null indicates no
|
||||||
|
completions are available.
|
||||||
|
*/
|
||||||
|
type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
|
||||||
|
/**
|
||||||
|
Interface for objects returned by completion sources.
|
||||||
|
*/
|
||||||
|
interface CompletionResult {
|
||||||
|
/**
|
||||||
|
The start of the range that is being completed.
|
||||||
|
*/
|
||||||
|
from: number;
|
||||||
|
/**
|
||||||
|
The end of the range that is being completed. Defaults to the
|
||||||
|
main cursor position.
|
||||||
|
*/
|
||||||
|
to?: number;
|
||||||
|
/**
|
||||||
|
The completions returned. These don't have to be compared with
|
||||||
|
the input by the source—the autocompletion system will do its
|
||||||
|
own matching (against the text between `from` and `to`) and
|
||||||
|
sorting.
|
||||||
|
*/
|
||||||
|
options: readonly Completion[];
|
||||||
|
/**
|
||||||
|
When given, further typing or deletion that causes the part of
|
||||||
|
the document between ([mapped](https://codemirror.net/6/docs/ref/#state.ChangeDesc.mapPos)) `from`
|
||||||
|
and `to` to match this regular expression or predicate function
|
||||||
|
will not query the completion source again, but continue with
|
||||||
|
this list of options. This can help a lot with responsiveness,
|
||||||
|
since it allows the completion list to be updated synchronously.
|
||||||
|
*/
|
||||||
|
validFor?: RegExp | ((text: string, from: number, to: number, state: EditorState) => boolean);
|
||||||
|
/**
|
||||||
|
By default, the library filters and scores completions. Set
|
||||||
|
`filter` to `false` to disable this, and cause your completions
|
||||||
|
to all be included, in the order they were given. When there are
|
||||||
|
other sources, unfiltered completions appear at the top of the
|
||||||
|
list of completions. `validFor` must not be given when `filter`
|
||||||
|
is `false`, because it only works when filtering.
|
||||||
|
*/
|
||||||
|
filter?: boolean;
|
||||||
|
/**
|
||||||
|
When [`filter`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.filter) is set to
|
||||||
|
`false` or a completion has a
|
||||||
|
[`displayLabel`](https://codemirror.net/6/docs/ref/#autocomplete.Completion.displayLabel), this
|
||||||
|
may be provided to compute the ranges on the label that match
|
||||||
|
the input. Should return an array of numbers where each pair of
|
||||||
|
adjacent numbers provide the start and end of a range. The
|
||||||
|
second argument, the match found by the library, is only passed
|
||||||
|
when `filter` isn't `false`.
|
||||||
|
*/
|
||||||
|
getMatch?: (completion: Completion, matched?: readonly number[]) => readonly number[];
|
||||||
|
/**
|
||||||
|
Synchronously update the completion result after typing or
|
||||||
|
deletion. If given, this should not do any expensive work, since
|
||||||
|
it will be called during editor state updates. The function
|
||||||
|
should make sure (similar to
|
||||||
|
[`validFor`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.validFor)) that the
|
||||||
|
completion still applies in the new state.
|
||||||
|
*/
|
||||||
|
update?: (current: CompletionResult, from: number, to: number, context: CompletionContext) => CompletionResult | null;
|
||||||
|
/**
|
||||||
|
When results contain position-dependent information in, for
|
||||||
|
example, `apply` methods, you can provide this method to update
|
||||||
|
the result for transactions that happen after the query. It is
|
||||||
|
not necessary to update `from` and `to`—those are tracked
|
||||||
|
automatically.
|
||||||
|
*/
|
||||||
|
map?: (current: CompletionResult, changes: ChangeDesc) => CompletionResult | null;
|
||||||
|
/**
|
||||||
|
Set a default set of [commit
|
||||||
|
characters](https://codemirror.net/6/docs/ref/#autocomplete.Completion.commitCharacters) for all
|
||||||
|
options in this result.
|
||||||
|
*/
|
||||||
|
commitCharacters?: readonly string[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
This annotation is added to transactions that are produced by
|
||||||
|
picking a completion.
|
||||||
|
*/
|
||||||
|
declare const pickedCompletion: _codemirror_state.AnnotationType<Completion>;
|
||||||
|
/**
|
||||||
|
Helper function that returns a transaction spec which inserts a
|
||||||
|
completion's text in the main selection range, and any other
|
||||||
|
selection range that has the same text in front of it.
|
||||||
|
*/
|
||||||
|
declare function insertCompletionText(state: EditorState, text: string, from: number, to: number): TransactionSpec;
|
||||||
|
|
||||||
|
interface CompletionConfig {
|
||||||
|
/**
|
||||||
|
When enabled (defaults to true), autocompletion will start
|
||||||
|
whenever the user types something that can be completed.
|
||||||
|
*/
|
||||||
|
activateOnTyping?: boolean;
|
||||||
|
/**
|
||||||
|
When given, if a completion that matches the predicate is
|
||||||
|
picked, reactivate completion again as if it was typed normally.
|
||||||
|
*/
|
||||||
|
activateOnCompletion?: (completion: Completion) => boolean;
|
||||||
|
/**
|
||||||
|
The amount of time to wait for further typing before querying
|
||||||
|
completion sources via
|
||||||
|
[`activateOnTyping`](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion^config.activateOnTyping).
|
||||||
|
Defaults to 100, which should be fine unless your completion
|
||||||
|
source is very slow and/or doesn't use `validFor`.
|
||||||
|
*/
|
||||||
|
activateOnTypingDelay?: number;
|
||||||
|
/**
|
||||||
|
By default, when completion opens, the first option is selected
|
||||||
|
and can be confirmed with
|
||||||
|
[`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion). When this
|
||||||
|
is set to false, the completion widget starts with no completion
|
||||||
|
selected, and the user has to explicitly move to a completion
|
||||||
|
before you can confirm one.
|
||||||
|
*/
|
||||||
|
selectOnOpen?: boolean;
|
||||||
|
/**
|
||||||
|
Override the completion sources used. By default, they will be
|
||||||
|
taken from the `"autocomplete"` [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) (which should hold
|
||||||
|
[completion sources](https://codemirror.net/6/docs/ref/#autocomplete.CompletionSource) or arrays
|
||||||
|
of [completions](https://codemirror.net/6/docs/ref/#autocomplete.Completion)).
|
||||||
|
*/
|
||||||
|
override?: readonly CompletionSource[] | null;
|
||||||
|
/**
|
||||||
|
Determines whether the completion tooltip is closed when the
|
||||||
|
editor loses focus. Defaults to true.
|
||||||
|
*/
|
||||||
|
closeOnBlur?: boolean;
|
||||||
|
/**
|
||||||
|
The maximum number of options to render to the DOM.
|
||||||
|
*/
|
||||||
|
maxRenderedOptions?: number;
|
||||||
|
/**
|
||||||
|
Set this to false to disable the [default completion
|
||||||
|
keymap](https://codemirror.net/6/docs/ref/#autocomplete.completionKeymap). (This requires you to
|
||||||
|
add bindings to control completion yourself. The bindings should
|
||||||
|
probably have a higher precedence than other bindings for the
|
||||||
|
same keys.)
|
||||||
|
*/
|
||||||
|
defaultKeymap?: boolean;
|
||||||
|
/**
|
||||||
|
By default, completions are shown below the cursor when there is
|
||||||
|
space. Setting this to true will make the extension put the
|
||||||
|
completions above the cursor when possible.
|
||||||
|
*/
|
||||||
|
aboveCursor?: boolean;
|
||||||
|
/**
|
||||||
|
When given, this may return an additional CSS class to add to
|
||||||
|
the completion dialog element.
|
||||||
|
*/
|
||||||
|
tooltipClass?: (state: EditorState) => string;
|
||||||
|
/**
|
||||||
|
This can be used to add additional CSS classes to completion
|
||||||
|
options.
|
||||||
|
*/
|
||||||
|
optionClass?: (completion: Completion) => string;
|
||||||
|
/**
|
||||||
|
By default, the library will render icons based on the
|
||||||
|
completion's [type](https://codemirror.net/6/docs/ref/#autocomplete.Completion.type) in front of
|
||||||
|
each option. Set this to false to turn that off.
|
||||||
|
*/
|
||||||
|
icons?: boolean;
|
||||||
|
/**
|
||||||
|
This option can be used to inject additional content into
|
||||||
|
options. The `render` function will be called for each visible
|
||||||
|
completion, and should produce a DOM node to show. `position`
|
||||||
|
determines where in the DOM the result appears, relative to
|
||||||
|
other added widgets and the standard content. The default icons
|
||||||
|
have position 20, the label position 50, and the detail position
|
||||||
|
80.
|
||||||
|
*/
|
||||||
|
addToOptions?: {
|
||||||
|
render: (completion: Completion, state: EditorState, view: EditorView) => Node | null;
|
||||||
|
position: number;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
By default, [info](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info) tooltips are
|
||||||
|
placed to the side of the selected completion. This option can
|
||||||
|
be used to override that. It will be given rectangles for the
|
||||||
|
list of completions, the selected option, the info element, and
|
||||||
|
the availble [tooltip
|
||||||
|
space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace), and should return
|
||||||
|
style and/or class strings for the info element.
|
||||||
|
*/
|
||||||
|
positionInfo?: (view: EditorView, list: Rect, option: Rect, info: Rect, space: Rect) => {
|
||||||
|
style?: string;
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
The comparison function to use when sorting completions with the same
|
||||||
|
match score. Defaults to using
|
||||||
|
[`localeCompare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare).
|
||||||
|
*/
|
||||||
|
compareCompletions?: (a: Completion, b: Completion) => number;
|
||||||
|
/**
|
||||||
|
When set to true (the default is false), turn off fuzzy matching
|
||||||
|
of completions and only show those that start with the text the
|
||||||
|
user typed. Only takes effect for results where
|
||||||
|
[`filter`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.filter) isn't false.
|
||||||
|
*/
|
||||||
|
filterStrict?: boolean;
|
||||||
|
/**
|
||||||
|
By default, commands relating to an open completion only take
|
||||||
|
effect 75 milliseconds after the completion opened, so that key
|
||||||
|
presses made before the user is aware of the tooltip don't go to
|
||||||
|
the tooltip. This option can be used to configure that delay.
|
||||||
|
*/
|
||||||
|
interactionDelay?: number;
|
||||||
|
/**
|
||||||
|
When there are multiple asynchronous completion sources, this
|
||||||
|
controls how long the extension waits for a slow source before
|
||||||
|
displaying results from faster sources. Defaults to 100
|
||||||
|
milliseconds.
|
||||||
|
*/
|
||||||
|
updateSyncTime?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert a snippet template to a function that can
|
||||||
|
[apply](https://codemirror.net/6/docs/ref/#autocomplete.Completion.apply) it. Snippets are written
|
||||||
|
using syntax like this:
|
||||||
|
|
||||||
|
"for (let ${index} = 0; ${index} < ${end}; ${index}++) {\n\t${}\n}"
|
||||||
|
|
||||||
|
Each `${}` placeholder (you may also use `#{}`) indicates a field
|
||||||
|
that the user can fill in. Its name, if any, will be the default
|
||||||
|
content for the field.
|
||||||
|
|
||||||
|
When the snippet is activated by calling the returned function,
|
||||||
|
the code is inserted at the given position. Newlines in the
|
||||||
|
template are indented by the indentation of the start line, plus
|
||||||
|
one [indent unit](https://codemirror.net/6/docs/ref/#language.indentUnit) per tab character after
|
||||||
|
the newline.
|
||||||
|
|
||||||
|
On activation, (all instances of) the first field are selected.
|
||||||
|
The user can move between fields with Tab and Shift-Tab as long as
|
||||||
|
the fields are active. Moving to the last field or moving the
|
||||||
|
cursor out of the current field deactivates the fields.
|
||||||
|
|
||||||
|
The order of fields defaults to textual order, but you can add
|
||||||
|
numbers to placeholders (`${1}` or `${1:defaultText}`) to provide
|
||||||
|
a custom order.
|
||||||
|
|
||||||
|
To include a literal `{` or `}` in your template, put a backslash
|
||||||
|
in front of it. This will be removed and the brace will not be
|
||||||
|
interpreted as indicating a placeholder.
|
||||||
|
*/
|
||||||
|
declare function snippet(template: string): (editor: {
|
||||||
|
state: EditorState;
|
||||||
|
dispatch: (tr: Transaction) => void;
|
||||||
|
}, completion: Completion | null, from: number, to: number) => void;
|
||||||
|
/**
|
||||||
|
A command that clears the active snippet, if any.
|
||||||
|
*/
|
||||||
|
declare const clearSnippet: StateCommand;
|
||||||
|
/**
|
||||||
|
Move to the next snippet field, if available.
|
||||||
|
*/
|
||||||
|
declare const nextSnippetField: StateCommand;
|
||||||
|
/**
|
||||||
|
Move to the previous snippet field, if available.
|
||||||
|
*/
|
||||||
|
declare const prevSnippetField: StateCommand;
|
||||||
|
/**
|
||||||
|
Check if there is an active snippet with a next field for
|
||||||
|
`nextSnippetField` to move to.
|
||||||
|
*/
|
||||||
|
declare function hasNextSnippetField(state: EditorState): boolean;
|
||||||
|
/**
|
||||||
|
Returns true if there is an active snippet and a previous field
|
||||||
|
for `prevSnippetField` to move to.
|
||||||
|
*/
|
||||||
|
declare function hasPrevSnippetField(state: EditorState): boolean;
|
||||||
|
/**
|
||||||
|
A facet that can be used to configure the key bindings used by
|
||||||
|
snippets. The default binds Tab to
|
||||||
|
[`nextSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.nextSnippetField), Shift-Tab to
|
||||||
|
[`prevSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.prevSnippetField), and Escape
|
||||||
|
to [`clearSnippet`](https://codemirror.net/6/docs/ref/#autocomplete.clearSnippet).
|
||||||
|
*/
|
||||||
|
declare const snippetKeymap: Facet<readonly KeyBinding[], readonly KeyBinding[]>;
|
||||||
|
/**
|
||||||
|
Create a completion from a snippet. Returns an object with the
|
||||||
|
properties from `completion`, plus an `apply` function that
|
||||||
|
applies the snippet.
|
||||||
|
*/
|
||||||
|
declare function snippetCompletion(template: string, completion: Completion): Completion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a command that moves the completion selection forward or
|
||||||
|
backward by the given amount.
|
||||||
|
*/
|
||||||
|
declare function moveCompletionSelection(forward: boolean, by?: "option" | "page"): Command;
|
||||||
|
/**
|
||||||
|
Accept the current completion.
|
||||||
|
*/
|
||||||
|
declare const acceptCompletion: Command;
|
||||||
|
/**
|
||||||
|
Explicitly start autocompletion.
|
||||||
|
*/
|
||||||
|
declare const startCompletion: Command;
|
||||||
|
/**
|
||||||
|
Close the currently active completion.
|
||||||
|
*/
|
||||||
|
declare const closeCompletion: Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
A completion source that will scan the document for words (using a
|
||||||
|
[character categorizer](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer)), and
|
||||||
|
return those as completions.
|
||||||
|
*/
|
||||||
|
declare const completeAnyWord: CompletionSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Configures bracket closing behavior for a syntax (via
|
||||||
|
[language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt)) using the `"closeBrackets"`
|
||||||
|
identifier.
|
||||||
|
*/
|
||||||
|
interface CloseBracketConfig {
|
||||||
|
/**
|
||||||
|
The opening brackets to close. Defaults to `["(", "[", "{", "'",
|
||||||
|
'"']`. Brackets may be single characters or a triple of quotes
|
||||||
|
(as in `"'''"`).
|
||||||
|
*/
|
||||||
|
brackets?: string[];
|
||||||
|
/**
|
||||||
|
Characters in front of which newly opened brackets are
|
||||||
|
automatically closed. Closing always happens in front of
|
||||||
|
whitespace. Defaults to `")]}:;>"`.
|
||||||
|
*/
|
||||||
|
before?: string;
|
||||||
|
/**
|
||||||
|
When determining whether a given node may be a string, recognize
|
||||||
|
these prefixes before the opening quote.
|
||||||
|
*/
|
||||||
|
stringPrefixes?: string[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Extension to enable bracket-closing behavior. When a closeable
|
||||||
|
bracket is typed, its closing bracket is immediately inserted
|
||||||
|
after the cursor. When closing a bracket directly in front of a
|
||||||
|
closing bracket inserted by the extension, the cursor moves over
|
||||||
|
that bracket.
|
||||||
|
*/
|
||||||
|
declare function closeBrackets(): Extension;
|
||||||
|
/**
|
||||||
|
Command that implements deleting a pair of matching brackets when
|
||||||
|
the cursor is between them.
|
||||||
|
*/
|
||||||
|
declare const deleteBracketPair: StateCommand;
|
||||||
|
/**
|
||||||
|
Close-brackets related key bindings. Binds Backspace to
|
||||||
|
[`deleteBracketPair`](https://codemirror.net/6/docs/ref/#autocomplete.deleteBracketPair).
|
||||||
|
*/
|
||||||
|
declare const closeBracketsKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
Implements the extension's behavior on text insertion. If the
|
||||||
|
given string counts as a bracket in the language around the
|
||||||
|
selection, and replacing the selection with it requires custom
|
||||||
|
behavior (inserting a closing version or skipping past a
|
||||||
|
previously-closed bracket), this function returns a transaction
|
||||||
|
representing that custom behavior. (You only need this if you want
|
||||||
|
to programmatically insert brackets—the
|
||||||
|
[`closeBrackets`](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets) extension will
|
||||||
|
take care of running this for user input.)
|
||||||
|
*/
|
||||||
|
declare function insertBracket(state: EditorState, bracket: string): Transaction | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an extension that enables autocompletion.
|
||||||
|
*/
|
||||||
|
declare function autocompletion(config?: CompletionConfig): Extension;
|
||||||
|
/**
|
||||||
|
Basic keybindings for autocompletion.
|
||||||
|
|
||||||
|
- Ctrl-Space (and Alt-\` or Alt-i on macOS): [`startCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.startCompletion)
|
||||||
|
- Escape: [`closeCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.closeCompletion)
|
||||||
|
- ArrowDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true)`
|
||||||
|
- ArrowUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false)`
|
||||||
|
- PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")`
|
||||||
|
- PageUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false, "page")`
|
||||||
|
- Enter: [`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion)
|
||||||
|
*/
|
||||||
|
declare const completionKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
Get the current completion status. When completions are available,
|
||||||
|
this will return `"active"`. When completions are pending (in the
|
||||||
|
process of being queried), this returns `"pending"`. Otherwise, it
|
||||||
|
returns `null`.
|
||||||
|
*/
|
||||||
|
declare function completionStatus(state: EditorState): null | "active" | "pending";
|
||||||
|
/**
|
||||||
|
Returns the available completions as an array.
|
||||||
|
*/
|
||||||
|
declare function currentCompletions(state: EditorState): readonly Completion[];
|
||||||
|
/**
|
||||||
|
Return the currently selected completion, if any.
|
||||||
|
*/
|
||||||
|
declare function selectedCompletion(state: EditorState): Completion | null;
|
||||||
|
/**
|
||||||
|
Returns the currently selected position in the active completion
|
||||||
|
list, or null if no completions are active.
|
||||||
|
*/
|
||||||
|
declare function selectedCompletionIndex(state: EditorState): number | null;
|
||||||
|
/**
|
||||||
|
Create an effect that can be attached to a transaction to change
|
||||||
|
the currently selected completion.
|
||||||
|
*/
|
||||||
|
declare function setSelectedCompletion(index: number): StateEffect<unknown>;
|
||||||
|
|
||||||
|
export { type CloseBracketConfig, type Completion, CompletionContext, type CompletionInfo, type CompletionResult, type CompletionSection, type CompletionSource, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, hasNextSnippetField, hasPrevSnippetField, ifIn, ifNotIn, insertBracket, insertCompletionText, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
|
||||||
2120
editor/node_modules/@codemirror/autocomplete/dist/index.js
generated
vendored
Normal file
2120
editor/node_modules/@codemirror/autocomplete/dist/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
41
editor/node_modules/@codemirror/autocomplete/package.json
generated
vendored
Normal file
41
editor/node_modules/@codemirror/autocomplete/package.json
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "@codemirror/autocomplete",
|
||||||
|
"version": "6.20.1",
|
||||||
|
"description": "Autocompletion for the CodeMirror code editor",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cm-runtests",
|
||||||
|
"prepare": "cm-buildhelper src/index.ts"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"code"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Marijn Haverbeke",
|
||||||
|
"email": "marijn@haverbeke.berlin",
|
||||||
|
"url": "http://marijnhaverbeke.nl"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"sideEffects": false,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.17.0",
|
||||||
|
"@lezer/common": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/buildhelper": "^1.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/codemirror/autocomplete.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
16
editor/node_modules/@codemirror/commands/.github/workflows/dispatch.yml
generated
vendored
Normal file
16
editor/node_modules/@codemirror/commands/.github/workflows/dispatch.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Trigger CI
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Dispatch to main repo
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Emit repository_dispatch
|
||||||
|
uses: mvasigh/dispatch-action@main
|
||||||
|
with:
|
||||||
|
# You should create a personal access token and store it in your repository
|
||||||
|
token: ${{ secrets.DISPATCH_AUTH }}
|
||||||
|
repo: dev
|
||||||
|
owner: codemirror
|
||||||
|
event_type: push
|
||||||
386
editor/node_modules/@codemirror/commands/CHANGELOG.md
generated
vendored
Normal file
386
editor/node_modules/@codemirror/commands/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
## 6.10.3 (2026-03-12)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure selection-extending commands preserve the associativity of the selection head.
|
||||||
|
|
||||||
|
## 6.10.2 (2026-02-06)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Move the selection to a less surprising place when undoing, moving the selection, redoing, then undoing again.
|
||||||
|
|
||||||
|
## 6.10.1 (2025-12-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where `copyLineDown` would leave the cursor on the wrong line when it was at the start of the line.
|
||||||
|
|
||||||
|
## 6.10.0 (2025-10-23)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `deleteGroupForwardWin` command provides by-group forward deletion using the Windows convention.
|
||||||
|
|
||||||
|
## 6.9.0 (2025-10-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Prevent the default behavior of backspace and delete keys, to prevent the browser from doing anything creative when there's nothing to delete.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Implement new `addCursorAbove` and `addCursorBelow` commands. Bind them to Mod-Alt-ArrowUp/Down in the default keymap.
|
||||||
|
|
||||||
|
## 6.8.1 (2025-03-31)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where creating a comment for a line that starts an inner language would use the comment style from the outer language.
|
||||||
|
|
||||||
|
## 6.8.0 (2025-01-08)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `cursorGroupForwardWin` and `selectGroupForwardWin` commands implement Windows-style forward motion by group.
|
||||||
|
|
||||||
|
## 6.7.1 (2024-10-21)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Change `toggleBlockCommentByLine` to not affect lines with the selection end right at their start.
|
||||||
|
|
||||||
|
## 6.7.0 (2024-10-07)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Bind Shift-Enter to the same command as Enter in the default keymap, so that it doesn't do nothing when on an EditContext-supporting browser.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Add commands for by-string-index cursor motion that ignores text direction.
|
||||||
|
|
||||||
|
## 6.6.2 (2024-09-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue causing `selectParentSyntax` to not select syntax that is a direct child of the top node.
|
||||||
|
|
||||||
|
Make `selectParentSyntax` return false when it doesn't change the selection.
|
||||||
|
|
||||||
|
## 6.6.1 (2024-08-31)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug in the undo history that would cause it to incorrectly track inverted effects when adding multiple edits to a single history event.
|
||||||
|
|
||||||
|
## 6.6.0 (2024-06-04)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `toggleTabFocusMode` and `temporarilySetTabFocusMode` commands provide control over the view's tab-focus mode.
|
||||||
|
|
||||||
|
The default keymap now binds Ctrl-m (Shift-Alt-m on macOS) to `toggleTabFocusMode`.
|
||||||
|
|
||||||
|
## 6.5.0 (2024-04-19)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `insertNewlineKeepIndent` command inserts a newline along with the same indentation as the line before.
|
||||||
|
|
||||||
|
## 6.4.0 (2024-04-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where `deleteLine` sometimes leaves the cursor on the wrong line.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `deleteCharBackwardStrict` command just deletes a character, without further smart behavior around indentation.
|
||||||
|
|
||||||
|
## 6.3.3 (2023-12-28)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue causing cursor motion commands to not dispatch a transaction when the change only affects cursor associativity.
|
||||||
|
|
||||||
|
## 6.3.2 (2023-11-28)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a regression that caused `deleteCharBackward` to sometimes delete a large chunk of text.
|
||||||
|
|
||||||
|
## 6.3.1 (2023-11-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
When undoing, store the selection after the undone change with the redo event, so that redoing restores it.
|
||||||
|
|
||||||
|
`deleteCharBackward` will no longer delete variant selector characters as separate characters.
|
||||||
|
|
||||||
|
## 6.3.0 (2023-09-29)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make it possible for `selectParentSyntax` to jump out of or into a syntax tree overlay.
|
||||||
|
|
||||||
|
Make Cmd-Backspace and Cmd-Delete on macOS delete to the next line wrap point, not the start/end of the line.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `deleteLineBoundaryForward` and `deleteLineBoundaryBackward` commands delete to the start/end of the line or the next line wrapping point.
|
||||||
|
|
||||||
|
## 6.2.5 (2023-08-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `insertNewlineAndIndent` properly count indentation for tabs when copying over the previous line's indentation.
|
||||||
|
|
||||||
|
The various sub-word motion commands will now use `Intl.Segmenter`, when available, to stop at CJK language word boundaries.
|
||||||
|
|
||||||
|
Fix a bug in `insertNewlineAndIndent` that would delete text between brackets if it had no corresponding AST node.
|
||||||
|
|
||||||
|
## 6.2.4 (2023-05-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
The by-subword motion commands now properly treat dashes, underscores, and similar as subword separators.
|
||||||
|
|
||||||
|
## 6.2.3 (2023-04-19)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Block commenting the selection no longer includes indentation on the first line.
|
||||||
|
|
||||||
|
## 6.2.2 (2023-03-10)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where line commenting got confused when commenting a range that crossed language boundaries.
|
||||||
|
|
||||||
|
## 6.2.1 (2023-02-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Keep cursor position stable in `cursorPageUp`/`cursorPageDown` when there are panels or other scroll margins active.
|
||||||
|
|
||||||
|
Make sure `toggleComment` doesn't get thrown off by local language nesting, by fetching the language data for the start of the selection line.
|
||||||
|
|
||||||
|
## 6.2.0 (2023-01-18)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `joinToEvent` history configuration option allows you to provide custom logic that determines whether a new transaction is added to an existing history event.
|
||||||
|
|
||||||
|
## 6.1.3 (2022-12-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Preserve selection bidi level when extending the selection, to prevent shift-selection from getting stuck in some kinds of bidirectional text.
|
||||||
|
|
||||||
|
## 6.1.2 (2022-10-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused deletion commands on non-empty ranges to incorrectly return false and do nothing, causing the editor to fall back to native behavior.
|
||||||
|
|
||||||
|
## 6.1.1 (2022-09-28)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure the selection endpoints are moved out of atomic ranges when applying a deletion command to a non-empty selection.
|
||||||
|
|
||||||
|
## 6.1.0 (2022-08-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Prevent native behavior on Ctrl/Cmd-ArrowLeft/ArrowRight bindings, so that browsers with odd bidi behavior won't do the wrong thing at start/end of line.
|
||||||
|
|
||||||
|
Cmd-ArrowLeft/Right on macOS now moves the cursor in the direction of the arrow even in right-to-left content.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `cursorLineBoundaryLeft`/`Right` and `selectLineBoundaryLeft`/`Right` commands allow directional motion to line boundaries.
|
||||||
|
|
||||||
|
## 6.0.1 (2022-06-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Announce to the screen reader when the selection is deleted.
|
||||||
|
|
||||||
|
Also bind Ctrl-Shift-z to redo on Linux.
|
||||||
|
|
||||||
|
## 6.0.0 (2022-06-08)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where by-page selection commands sometimes moved one line too far.
|
||||||
|
|
||||||
|
## 0.20.0 (2022-04-20)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
There is no longer a separate `commentKeymap`. Those bindings are now part of `defaultKeymap`.
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `cursorPageUp` and `cursorPageDown` move by window height when the editor is higher than the window.
|
||||||
|
|
||||||
|
Make sure the default behavior of Home/End is prevented, since it could produce unexpected results on macOS.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The exports from @codemirror/comment are now available in this package.
|
||||||
|
|
||||||
|
The exports from the @codemirror/history package are now available from this package.
|
||||||
|
|
||||||
|
## 0.19.8 (2022-01-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
`deleteCharBackward` now removes extending characters one at a time, rather than deleting the entire glyph at once.
|
||||||
|
|
||||||
|
Alt-v is no longer bound in `emacsStyleKeymap` and macOS's `standardKeymap`, because macOS doesn't bind it by default and it conflicts with some keyboard layouts.
|
||||||
|
|
||||||
|
## 0.19.7 (2022-01-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't bind Alt-\< and Alt-> on macOS by default, since those interfere with some keyboard layouts. Make cursorPageUp/Down scroll the view to keep the cursor in place
|
||||||
|
|
||||||
|
`cursorPageUp` and `cursorPageDown` now scroll the view by the amount that the cursor moved.
|
||||||
|
|
||||||
|
## 0.19.6 (2021-12-10)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
The standard keymap no longer overrides Shift-Delete, in order to allow the native behavior of that key to happen on platforms that support it.
|
||||||
|
|
||||||
|
## 0.19.5 (2021-09-21)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Adds an `insertBlankLine` command which creates an empty line below the selection, and binds it to Mod-Enter in the default keymap.
|
||||||
|
|
||||||
|
## 0.19.4 (2021-09-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make commands that affect the editor's content check `state.readOnly` and return false when that is true.
|
||||||
|
|
||||||
|
## 0.19.3 (2021-09-09)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make by-line cursor motion commands move the cursor to the start/end of the document when they hit the first/last line.
|
||||||
|
|
||||||
|
Fix a bug where `deleteCharForward`/`Backward` behaved incorrectly when deleting directly before or after an atomic range.
|
||||||
|
|
||||||
|
## 0.19.2 (2021-08-24)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
New commands `cursorSubwordForward`, `cursorSubwordBackward`, `selectSubwordForward`, and `selectSubwordBackward` which implement motion by camel case subword.
|
||||||
|
|
||||||
|
## 0.19.1 (2021-08-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix incorrect versions for @lezer dependencies.
|
||||||
|
|
||||||
|
## 0.19.0 (2021-08-11)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Change default binding for backspace to `deleteCharBackward`, drop `deleteCodePointBackward`/`Forward` from the library.
|
||||||
|
|
||||||
|
`defaultTabBinding` was removed.
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Drop Alt-d, Alt-f, and Alt-b bindings from `emacsStyleKeymap` (and thus from the default macOS bindings).
|
||||||
|
|
||||||
|
`deleteCharBackward` and `deleteCharForward` now take atomic ranges into account.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Attach more granular user event strings to transactions.
|
||||||
|
|
||||||
|
The module exports a new binding `indentWithTab` that binds tab and shift-tab to `indentMore` and `indentLess`.
|
||||||
|
|
||||||
|
## 0.18.3 (2021-06-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
`moveLineDown` will no longer incorrectly grow the selection.
|
||||||
|
|
||||||
|
Line-based commands will no longer include lines where a range selection ends right at the start of the line.
|
||||||
|
|
||||||
|
## 0.18.2 (2021-05-06)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Use Ctrl-l, not Alt-l, to bind `selectLine` on macOS, to avoid conflicting with special-character-insertion bindings.
|
||||||
|
|
||||||
|
Make the macOS Command-ArrowLeft/Right commands behave more like their native versions.
|
||||||
|
|
||||||
|
## 0.18.1 (2021-04-08)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Also bind Shift-Backspace and Shift-Delete in the default keymap (to do the same thing as the Shift-less binding).
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Adds a `deleteToLineStart` command.
|
||||||
|
|
||||||
|
Adds bindings for Cmd-Delete and Cmd-Backspace on macOS.
|
||||||
|
|
||||||
|
## 0.18.0 (2021-03-03)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 0.18.
|
||||||
|
|
||||||
|
## 0.17.5 (2021-02-25)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Use Alt-l for the default `selectLine` binding, because Mod-l already has an important meaning in the browser.
|
||||||
|
|
||||||
|
Make `deleteGroupBackward`/`deleteGroupForward` delete groups of whitespace when bigger than a single space.
|
||||||
|
|
||||||
|
Don't change lines that have the end of a range selection directly at their start in `indentLess`, `indentMore`, and `indentSelection`.
|
||||||
|
|
||||||
|
## 0.17.4 (2021-02-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where `deleteToLineEnd` would delete the rest of the document when at the end of a line.
|
||||||
|
|
||||||
|
## 0.17.3 (2021-02-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where `insertNewlineAndIndent` behaved strangely with the cursor between brackets that sat on different lines.
|
||||||
|
|
||||||
|
## 0.17.2 (2021-01-22)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `insertTab` command inserts a tab when nothing is selected, and defers to `indentMore` otherwise.
|
||||||
|
|
||||||
|
The package now exports a `defaultTabBinding` object that provides a recommended binding for tab (if you must bind tab).
|
||||||
|
|
||||||
|
## 0.17.1 (2021-01-06)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now also exports a CommonJS module.
|
||||||
|
|
||||||
|
## 0.17.0 (2020-12-29)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
First numbered release.
|
||||||
|
|
||||||
21
editor/node_modules/@codemirror/commands/LICENSE
generated
vendored
Normal file
21
editor/node_modules/@codemirror/commands/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
35
editor/node_modules/@codemirror/commands/README.md
generated
vendored
Normal file
35
editor/node_modules/@codemirror/commands/README.md
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# @codemirror/commands [](https://www.npmjs.org/package/@codemirror/commands)
|
||||||
|
|
||||||
|
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#commands) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/commands/blob/main/CHANGELOG.md) ]
|
||||||
|
|
||||||
|
This package implements a collection of editing commands for the
|
||||||
|
[CodeMirror](https://codemirror.net/) code editor.
|
||||||
|
|
||||||
|
The [project page](https://codemirror.net/) has more information, a
|
||||||
|
number of [examples](https://codemirror.net/examples/) and the
|
||||||
|
[documentation](https://codemirror.net/docs/).
|
||||||
|
|
||||||
|
This code is released under an
|
||||||
|
[MIT license](https://github.com/codemirror/commands/tree/main/LICENSE).
|
||||||
|
|
||||||
|
We aim to be an inclusive, welcoming community. To make that explicit,
|
||||||
|
we have a [code of
|
||||||
|
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
||||||
|
to communication around the project.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {EditorView, keymap} from "@codemirror/view"
|
||||||
|
import {standardKeymap, selectLine} from "@codemirror/commands"
|
||||||
|
|
||||||
|
const view = new EditorView({
|
||||||
|
parent: document.body,
|
||||||
|
extensions: [
|
||||||
|
keymap.of([
|
||||||
|
...standardKeymap,
|
||||||
|
{key: "Alt-l", mac: "Ctrl-l", run: selectLine}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
})
|
||||||
|
```
|
||||||
1909
editor/node_modules/@codemirror/commands/dist/index.cjs
generated
vendored
Normal file
1909
editor/node_modules/@codemirror/commands/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
650
editor/node_modules/@codemirror/commands/dist/index.d.cts
generated
vendored
Normal file
650
editor/node_modules/@codemirror/commands/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,650 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { StateCommand, Facet, Transaction, StateEffect, Extension, StateField, EditorState } from '@codemirror/state';
|
||||||
|
import { KeyBinding, Command } from '@codemirror/view';
|
||||||
|
|
||||||
|
/**
|
||||||
|
An object of this type can be provided as [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) under a `"commentTokens"`
|
||||||
|
property to configure comment syntax for a language.
|
||||||
|
*/
|
||||||
|
interface CommentTokens {
|
||||||
|
/**
|
||||||
|
The block comment syntax, if any. For example, for HTML
|
||||||
|
you'd provide `{open: "<!--", close: "-->"}`.
|
||||||
|
*/
|
||||||
|
block?: {
|
||||||
|
open: string;
|
||||||
|
close: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
The line comment syntax. For example `"//"`.
|
||||||
|
*/
|
||||||
|
line?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Comment or uncomment the current selection. Will use line comments
|
||||||
|
if available, otherwise falling back to block comments.
|
||||||
|
*/
|
||||||
|
declare const toggleComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment or uncomment the current selection using line comments.
|
||||||
|
The line comment syntax is taken from the
|
||||||
|
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||||
|
*/
|
||||||
|
declare const toggleLineComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment the current selection using line comments.
|
||||||
|
*/
|
||||||
|
declare const lineComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Uncomment the current selection using line comments.
|
||||||
|
*/
|
||||||
|
declare const lineUncomment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment or uncomment the current selection using block comments.
|
||||||
|
The block comment syntax is taken from the
|
||||||
|
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||||
|
*/
|
||||||
|
declare const toggleBlockComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment the current selection using block comments.
|
||||||
|
*/
|
||||||
|
declare const blockComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Uncomment the current selection using block comments.
|
||||||
|
*/
|
||||||
|
declare const blockUncomment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment or uncomment the lines around the current selection using
|
||||||
|
block comments.
|
||||||
|
*/
|
||||||
|
declare const toggleBlockCommentByLine: StateCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Transaction annotation that will prevent that transaction from
|
||||||
|
being combined with other transactions in the undo history. Given
|
||||||
|
`"before"`, it'll prevent merging with previous transactions. With
|
||||||
|
`"after"`, subsequent transactions won't be combined with this
|
||||||
|
one. With `"full"`, the transaction is isolated on both sides.
|
||||||
|
*/
|
||||||
|
declare const isolateHistory: _codemirror_state.AnnotationType<"after" | "before" | "full">;
|
||||||
|
/**
|
||||||
|
This facet provides a way to register functions that, given a
|
||||||
|
transaction, provide a set of effects that the history should
|
||||||
|
store when inverting the transaction. This can be used to
|
||||||
|
integrate some kinds of effects in the history, so that they can
|
||||||
|
be undone (and redone again).
|
||||||
|
*/
|
||||||
|
declare const invertedEffects: Facet<(tr: Transaction) => readonly StateEffect<any>[], readonly ((tr: Transaction) => readonly StateEffect<any>[])[]>;
|
||||||
|
interface HistoryConfig {
|
||||||
|
/**
|
||||||
|
The minimum depth (amount of events) to store. Defaults to 100.
|
||||||
|
*/
|
||||||
|
minDepth?: number;
|
||||||
|
/**
|
||||||
|
The maximum time (in milliseconds) that adjacent events can be
|
||||||
|
apart and still be grouped together. Defaults to 500.
|
||||||
|
*/
|
||||||
|
newGroupDelay?: number;
|
||||||
|
/**
|
||||||
|
By default, when close enough together in time, changes are
|
||||||
|
joined into an existing undo event if they touch any of the
|
||||||
|
changed ranges from that event. You can pass a custom predicate
|
||||||
|
here to influence that logic.
|
||||||
|
*/
|
||||||
|
joinToEvent?: (tr: Transaction, isAdjacent: boolean) => boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Create a history extension with the given configuration.
|
||||||
|
*/
|
||||||
|
declare function history(config?: HistoryConfig): Extension;
|
||||||
|
/**
|
||||||
|
The state field used to store the history data. Should probably
|
||||||
|
only be used when you want to
|
||||||
|
[serialize](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) or
|
||||||
|
[deserialize](https://codemirror.net/6/docs/ref/#state.EditorState^fromJSON) state objects in a way
|
||||||
|
that preserves history.
|
||||||
|
*/
|
||||||
|
declare const historyField: StateField<unknown>;
|
||||||
|
/**
|
||||||
|
Undo a single group of history events. Returns false if no group
|
||||||
|
was available.
|
||||||
|
*/
|
||||||
|
declare const undo: StateCommand;
|
||||||
|
/**
|
||||||
|
Redo a group of history events. Returns false if no group was
|
||||||
|
available.
|
||||||
|
*/
|
||||||
|
declare const redo: StateCommand;
|
||||||
|
/**
|
||||||
|
Undo a change or selection change.
|
||||||
|
*/
|
||||||
|
declare const undoSelection: StateCommand;
|
||||||
|
/**
|
||||||
|
Redo a change or selection change.
|
||||||
|
*/
|
||||||
|
declare const redoSelection: StateCommand;
|
||||||
|
/**
|
||||||
|
The amount of undoable change events available in a given state.
|
||||||
|
*/
|
||||||
|
declare const undoDepth: (state: EditorState) => number;
|
||||||
|
/**
|
||||||
|
The amount of redoable change events available in a given state.
|
||||||
|
*/
|
||||||
|
declare const redoDepth: (state: EditorState) => number;
|
||||||
|
/**
|
||||||
|
Default key bindings for the undo history.
|
||||||
|
|
||||||
|
- Mod-z: [`undo`](https://codemirror.net/6/docs/ref/#commands.undo).
|
||||||
|
- Mod-y (Mod-Shift-z on macOS) + Ctrl-Shift-z on Linux: [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||||
|
- Mod-u: [`undoSelection`](https://codemirror.net/6/docs/ref/#commands.undoSelection).
|
||||||
|
- Alt-u (Mod-Shift-u on macOS): [`redoSelection`](https://codemirror.net/6/docs/ref/#commands.redoSelection).
|
||||||
|
*/
|
||||||
|
declare const historyKeymap: readonly KeyBinding[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
Move the selection one character to the left (which is backward in
|
||||||
|
left-to-right text, forward in right-to-left text).
|
||||||
|
*/
|
||||||
|
declare const cursorCharLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorCharRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character forward.
|
||||||
|
*/
|
||||||
|
declare const cursorCharForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character backward.
|
||||||
|
*/
|
||||||
|
declare const cursorCharBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character forward, in logical
|
||||||
|
(non-text-direction-aware) string index order.
|
||||||
|
*/
|
||||||
|
declare const cursorCharForwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection one character backward, in logical string index
|
||||||
|
order.
|
||||||
|
*/
|
||||||
|
declare const cursorCharBackwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection to the left across one group of word or
|
||||||
|
non-word (but also non-space) characters.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group forward.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group backward.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the cursor one group forward in the default Windows style,
|
||||||
|
where it moves to the start of the next group.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupForwardWin: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group or camel-case subword forward.
|
||||||
|
*/
|
||||||
|
declare const cursorSubwordForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group or camel-case subword backward.
|
||||||
|
*/
|
||||||
|
declare const cursorSubwordBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the cursor over the next syntactic element to the left.
|
||||||
|
*/
|
||||||
|
declare const cursorSyntaxLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the cursor over the next syntactic element to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorSyntaxRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line up.
|
||||||
|
*/
|
||||||
|
declare const cursorLineUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line down.
|
||||||
|
*/
|
||||||
|
declare const cursorLineDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one page up.
|
||||||
|
*/
|
||||||
|
declare const cursorPageUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one page down.
|
||||||
|
*/
|
||||||
|
declare const cursorPageDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the next line wrap point, or to the end of
|
||||||
|
the line if there isn't one left on this line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to previous line wrap point, or failing that to
|
||||||
|
the start of the line. If the line is indented, and the cursor
|
||||||
|
isn't already at the end of the indentation, this will move to the
|
||||||
|
end of the indentation instead of the start of the line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line wrap point to the left.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line wrap point to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the start of the line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineStart: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the end of the line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineEnd: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the bracket matching the one it is currently
|
||||||
|
on, if any.
|
||||||
|
*/
|
||||||
|
declare const cursorMatchingBracket: StateCommand;
|
||||||
|
/**
|
||||||
|
Extend the selection to the bracket matching the one the selection
|
||||||
|
head is currently on, if any.
|
||||||
|
*/
|
||||||
|
declare const selectMatchingBracket: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head one character to the left, while leaving
|
||||||
|
the anchor in place.
|
||||||
|
*/
|
||||||
|
declare const selectCharLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character to the right.
|
||||||
|
*/
|
||||||
|
declare const selectCharRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character forward.
|
||||||
|
*/
|
||||||
|
declare const selectCharForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character backward.
|
||||||
|
*/
|
||||||
|
declare const selectCharBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character forward by logical
|
||||||
|
(non-direction aware) string index order.
|
||||||
|
*/
|
||||||
|
declare const selectCharForwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head one character backward by logical string
|
||||||
|
index order.
|
||||||
|
*/
|
||||||
|
declare const selectCharBackwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head one [group](https://codemirror.net/6/docs/ref/#commands.cursorGroupLeft) to
|
||||||
|
the left.
|
||||||
|
*/
|
||||||
|
declare const selectGroupLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group to the right.
|
||||||
|
*/
|
||||||
|
declare const selectGroupRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group forward.
|
||||||
|
*/
|
||||||
|
declare const selectGroupForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group backward.
|
||||||
|
*/
|
||||||
|
declare const selectGroupBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group forward in the default Windows
|
||||||
|
style, skipping to the start of the next group.
|
||||||
|
*/
|
||||||
|
declare const selectGroupForwardWin: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group or camel-case subword forward.
|
||||||
|
*/
|
||||||
|
declare const selectSubwordForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group or subword backward.
|
||||||
|
*/
|
||||||
|
declare const selectSubwordBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head over the next syntactic element to the left.
|
||||||
|
*/
|
||||||
|
declare const selectSyntaxLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head over the next syntactic element to the right.
|
||||||
|
*/
|
||||||
|
declare const selectSyntaxRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line up.
|
||||||
|
*/
|
||||||
|
declare const selectLineUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line down.
|
||||||
|
*/
|
||||||
|
declare const selectLineDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one page up.
|
||||||
|
*/
|
||||||
|
declare const selectPageUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one page down.
|
||||||
|
*/
|
||||||
|
declare const selectPageDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the next line boundary.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the previous line boundary.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line boundary to the left.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line boundary to the right.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the start of the line.
|
||||||
|
*/
|
||||||
|
declare const selectLineStart: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the end of the line.
|
||||||
|
*/
|
||||||
|
declare const selectLineEnd: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the start of the document.
|
||||||
|
*/
|
||||||
|
declare const cursorDocStart: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection to the end of the document.
|
||||||
|
*/
|
||||||
|
declare const cursorDocEnd: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head to the start of the document.
|
||||||
|
*/
|
||||||
|
declare const selectDocStart: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head to the end of the document.
|
||||||
|
*/
|
||||||
|
declare const selectDocEnd: StateCommand;
|
||||||
|
/**
|
||||||
|
Select the entire document.
|
||||||
|
*/
|
||||||
|
declare const selectAll: StateCommand;
|
||||||
|
/**
|
||||||
|
Expand the selection to cover entire lines.
|
||||||
|
*/
|
||||||
|
declare const selectLine: StateCommand;
|
||||||
|
/**
|
||||||
|
Select the next syntactic construct that is larger than the
|
||||||
|
selection. Note that this will only work insofar as the language
|
||||||
|
[provider](https://codemirror.net/6/docs/ref/#language.language) you use builds up a full
|
||||||
|
syntax tree.
|
||||||
|
*/
|
||||||
|
declare const selectParentSyntax: StateCommand;
|
||||||
|
/**
|
||||||
|
Expand the selection by adding a cursor above the heads of
|
||||||
|
currently selected ranges.
|
||||||
|
*/
|
||||||
|
declare const addCursorAbove: Command;
|
||||||
|
/**
|
||||||
|
Expand the selection by adding a cursor below the heads of
|
||||||
|
currently selected ranges.
|
||||||
|
*/
|
||||||
|
declare const addCursorBelow: Command;
|
||||||
|
/**
|
||||||
|
Simplify the current selection. When multiple ranges are selected,
|
||||||
|
reduce it to its main range. Otherwise, if the selection is
|
||||||
|
non-empty, convert it to a cursor selection.
|
||||||
|
*/
|
||||||
|
declare const simplifySelection: StateCommand;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, for cursor selections, the character or
|
||||||
|
indentation unit before the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteCharBackward: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection or the character before the cursor. Does not
|
||||||
|
implement any extended behavior like deleting whole indentation
|
||||||
|
units in one go.
|
||||||
|
*/
|
||||||
|
declare const deleteCharBackwardStrict: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection or the character after the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteCharForward: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection or backward until the end of the next
|
||||||
|
[group](https://codemirror.net/6/docs/ref/#view.EditorView.moveByGroup), only skipping groups of
|
||||||
|
whitespace when they consist of a single space.
|
||||||
|
*/
|
||||||
|
declare const deleteGroupBackward: StateCommand;
|
||||||
|
/**
|
||||||
|
Delete the selection or forward until the end of the next group.
|
||||||
|
*/
|
||||||
|
declare const deleteGroupForward: StateCommand;
|
||||||
|
/**
|
||||||
|
Variant of [`deleteGroupForward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupForward)
|
||||||
|
that uses the Windows convention of also deleting the whitespace
|
||||||
|
after a word.
|
||||||
|
*/
|
||||||
|
declare const deleteGroupForwardWin: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the end of the line. If the cursor is directly at the end of the
|
||||||
|
line, delete the line break after it.
|
||||||
|
*/
|
||||||
|
declare const deleteToLineEnd: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the start of the line. If the cursor is directly at the start of the
|
||||||
|
line, delete the line break before it.
|
||||||
|
*/
|
||||||
|
declare const deleteToLineStart: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the start of the line or the next line wrap before the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteLineBoundaryBackward: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the end of the line or the next line wrap after the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteLineBoundaryForward: Command;
|
||||||
|
/**
|
||||||
|
Delete all whitespace directly before a line end from the
|
||||||
|
document.
|
||||||
|
*/
|
||||||
|
declare const deleteTrailingWhitespace: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace each selection range with a line break, leaving the cursor
|
||||||
|
on the line before the break.
|
||||||
|
*/
|
||||||
|
declare const splitLine: StateCommand;
|
||||||
|
/**
|
||||||
|
Flip the characters before and after the cursor(s).
|
||||||
|
*/
|
||||||
|
declare const transposeChars: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selected lines up one line.
|
||||||
|
*/
|
||||||
|
declare const moveLineUp: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selected lines down one line.
|
||||||
|
*/
|
||||||
|
declare const moveLineDown: StateCommand;
|
||||||
|
/**
|
||||||
|
Create a copy of the selected lines. Keep the selection in the top copy.
|
||||||
|
*/
|
||||||
|
declare const copyLineUp: StateCommand;
|
||||||
|
/**
|
||||||
|
Create a copy of the selected lines. Keep the selection in the bottom copy.
|
||||||
|
*/
|
||||||
|
declare const copyLineDown: StateCommand;
|
||||||
|
/**
|
||||||
|
Delete selected lines.
|
||||||
|
*/
|
||||||
|
declare const deleteLine: Command;
|
||||||
|
/**
|
||||||
|
Replace the selection with a newline.
|
||||||
|
*/
|
||||||
|
declare const insertNewline: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace the selection with a newline and the same amount of
|
||||||
|
indentation as the line above.
|
||||||
|
*/
|
||||||
|
declare const insertNewlineKeepIndent: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace the selection with a newline and indent the newly created
|
||||||
|
line(s). If the current line consists only of whitespace, this
|
||||||
|
will also delete that whitespace. When the cursor is between
|
||||||
|
matching brackets, an additional newline will be inserted after
|
||||||
|
the cursor.
|
||||||
|
*/
|
||||||
|
declare const insertNewlineAndIndent: StateCommand;
|
||||||
|
/**
|
||||||
|
Create a blank, indented line below the current line.
|
||||||
|
*/
|
||||||
|
declare const insertBlankLine: StateCommand;
|
||||||
|
/**
|
||||||
|
Auto-indent the selected lines. This uses the [indentation service
|
||||||
|
facet](https://codemirror.net/6/docs/ref/#language.indentService) as source for auto-indent
|
||||||
|
information.
|
||||||
|
*/
|
||||||
|
declare const indentSelection: StateCommand;
|
||||||
|
/**
|
||||||
|
Add a [unit](https://codemirror.net/6/docs/ref/#language.indentUnit) of indentation to all selected
|
||||||
|
lines.
|
||||||
|
*/
|
||||||
|
declare const indentMore: StateCommand;
|
||||||
|
/**
|
||||||
|
Remove a [unit](https://codemirror.net/6/docs/ref/#language.indentUnit) of indentation from all
|
||||||
|
selected lines.
|
||||||
|
*/
|
||||||
|
declare const indentLess: StateCommand;
|
||||||
|
/**
|
||||||
|
Enables or disables
|
||||||
|
[tab-focus mode](https://codemirror.net/6/docs/ref/#view.EditorView.setTabFocusMode). While on, this
|
||||||
|
prevents the editor's key bindings from capturing Tab or
|
||||||
|
Shift-Tab, making it possible for the user to move focus out of
|
||||||
|
the editor with the keyboard.
|
||||||
|
*/
|
||||||
|
declare const toggleTabFocusMode: Command;
|
||||||
|
/**
|
||||||
|
Temporarily enables [tab-focus
|
||||||
|
mode](https://codemirror.net/6/docs/ref/#view.EditorView.setTabFocusMode) for two seconds or until
|
||||||
|
another key is pressed.
|
||||||
|
*/
|
||||||
|
declare const temporarilySetTabFocusMode: Command;
|
||||||
|
/**
|
||||||
|
Insert a tab character at the cursor or, if something is selected,
|
||||||
|
use [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) to indent the entire
|
||||||
|
selection.
|
||||||
|
*/
|
||||||
|
declare const insertTab: StateCommand;
|
||||||
|
/**
|
||||||
|
Array of key bindings containing the Emacs-style bindings that are
|
||||||
|
available on macOS by default.
|
||||||
|
|
||||||
|
- Ctrl-b: [`cursorCharLeft`](https://codemirror.net/6/docs/ref/#commands.cursorCharLeft) ([`selectCharLeft`](https://codemirror.net/6/docs/ref/#commands.selectCharLeft) with Shift)
|
||||||
|
- Ctrl-f: [`cursorCharRight`](https://codemirror.net/6/docs/ref/#commands.cursorCharRight) ([`selectCharRight`](https://codemirror.net/6/docs/ref/#commands.selectCharRight) with Shift)
|
||||||
|
- Ctrl-p: [`cursorLineUp`](https://codemirror.net/6/docs/ref/#commands.cursorLineUp) ([`selectLineUp`](https://codemirror.net/6/docs/ref/#commands.selectLineUp) with Shift)
|
||||||
|
- Ctrl-n: [`cursorLineDown`](https://codemirror.net/6/docs/ref/#commands.cursorLineDown) ([`selectLineDown`](https://codemirror.net/6/docs/ref/#commands.selectLineDown) with Shift)
|
||||||
|
- Ctrl-a: [`cursorLineStart`](https://codemirror.net/6/docs/ref/#commands.cursorLineStart) ([`selectLineStart`](https://codemirror.net/6/docs/ref/#commands.selectLineStart) with Shift)
|
||||||
|
- Ctrl-e: [`cursorLineEnd`](https://codemirror.net/6/docs/ref/#commands.cursorLineEnd) ([`selectLineEnd`](https://codemirror.net/6/docs/ref/#commands.selectLineEnd) with Shift)
|
||||||
|
- Ctrl-d: [`deleteCharForward`](https://codemirror.net/6/docs/ref/#commands.deleteCharForward)
|
||||||
|
- Ctrl-h: [`deleteCharBackward`](https://codemirror.net/6/docs/ref/#commands.deleteCharBackward)
|
||||||
|
- Ctrl-k: [`deleteToLineEnd`](https://codemirror.net/6/docs/ref/#commands.deleteToLineEnd)
|
||||||
|
- Ctrl-Alt-h: [`deleteGroupBackward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupBackward)
|
||||||
|
- Ctrl-o: [`splitLine`](https://codemirror.net/6/docs/ref/#commands.splitLine)
|
||||||
|
- Ctrl-t: [`transposeChars`](https://codemirror.net/6/docs/ref/#commands.transposeChars)
|
||||||
|
- Ctrl-v: [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown)
|
||||||
|
- Alt-v: [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp)
|
||||||
|
*/
|
||||||
|
declare const emacsStyleKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
An array of key bindings closely sticking to platform-standard or
|
||||||
|
widely used bindings. (This includes the bindings from
|
||||||
|
[`emacsStyleKeymap`](https://codemirror.net/6/docs/ref/#commands.emacsStyleKeymap), with their `key`
|
||||||
|
property changed to `mac`.)
|
||||||
|
|
||||||
|
- ArrowLeft: [`cursorCharLeft`](https://codemirror.net/6/docs/ref/#commands.cursorCharLeft) ([`selectCharLeft`](https://codemirror.net/6/docs/ref/#commands.selectCharLeft) with Shift)
|
||||||
|
- ArrowRight: [`cursorCharRight`](https://codemirror.net/6/docs/ref/#commands.cursorCharRight) ([`selectCharRight`](https://codemirror.net/6/docs/ref/#commands.selectCharRight) with Shift)
|
||||||
|
- Ctrl-ArrowLeft (Alt-ArrowLeft on macOS): [`cursorGroupLeft`](https://codemirror.net/6/docs/ref/#commands.cursorGroupLeft) ([`selectGroupLeft`](https://codemirror.net/6/docs/ref/#commands.selectGroupLeft) with Shift)
|
||||||
|
- Ctrl-ArrowRight (Alt-ArrowRight on macOS): [`cursorGroupRight`](https://codemirror.net/6/docs/ref/#commands.cursorGroupRight) ([`selectGroupRight`](https://codemirror.net/6/docs/ref/#commands.selectGroupRight) with Shift)
|
||||||
|
- Cmd-ArrowLeft (on macOS): [`cursorLineStart`](https://codemirror.net/6/docs/ref/#commands.cursorLineStart) ([`selectLineStart`](https://codemirror.net/6/docs/ref/#commands.selectLineStart) with Shift)
|
||||||
|
- Cmd-ArrowRight (on macOS): [`cursorLineEnd`](https://codemirror.net/6/docs/ref/#commands.cursorLineEnd) ([`selectLineEnd`](https://codemirror.net/6/docs/ref/#commands.selectLineEnd) with Shift)
|
||||||
|
- ArrowUp: [`cursorLineUp`](https://codemirror.net/6/docs/ref/#commands.cursorLineUp) ([`selectLineUp`](https://codemirror.net/6/docs/ref/#commands.selectLineUp) with Shift)
|
||||||
|
- ArrowDown: [`cursorLineDown`](https://codemirror.net/6/docs/ref/#commands.cursorLineDown) ([`selectLineDown`](https://codemirror.net/6/docs/ref/#commands.selectLineDown) with Shift)
|
||||||
|
- Cmd-ArrowUp (on macOS): [`cursorDocStart`](https://codemirror.net/6/docs/ref/#commands.cursorDocStart) ([`selectDocStart`](https://codemirror.net/6/docs/ref/#commands.selectDocStart) with Shift)
|
||||||
|
- Cmd-ArrowDown (on macOS): [`cursorDocEnd`](https://codemirror.net/6/docs/ref/#commands.cursorDocEnd) ([`selectDocEnd`](https://codemirror.net/6/docs/ref/#commands.selectDocEnd) with Shift)
|
||||||
|
- Ctrl-ArrowUp (on macOS): [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp) ([`selectPageUp`](https://codemirror.net/6/docs/ref/#commands.selectPageUp) with Shift)
|
||||||
|
- Ctrl-ArrowDown (on macOS): [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown) ([`selectPageDown`](https://codemirror.net/6/docs/ref/#commands.selectPageDown) with Shift)
|
||||||
|
- PageUp: [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp) ([`selectPageUp`](https://codemirror.net/6/docs/ref/#commands.selectPageUp) with Shift)
|
||||||
|
- PageDown: [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown) ([`selectPageDown`](https://codemirror.net/6/docs/ref/#commands.selectPageDown) with Shift)
|
||||||
|
- Home: [`cursorLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.cursorLineBoundaryBackward) ([`selectLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.selectLineBoundaryBackward) with Shift)
|
||||||
|
- End: [`cursorLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.cursorLineBoundaryForward) ([`selectLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.selectLineBoundaryForward) with Shift)
|
||||||
|
- Ctrl-Home (Cmd-Home on macOS): [`cursorDocStart`](https://codemirror.net/6/docs/ref/#commands.cursorDocStart) ([`selectDocStart`](https://codemirror.net/6/docs/ref/#commands.selectDocStart) with Shift)
|
||||||
|
- Ctrl-End (Cmd-Home on macOS): [`cursorDocEnd`](https://codemirror.net/6/docs/ref/#commands.cursorDocEnd) ([`selectDocEnd`](https://codemirror.net/6/docs/ref/#commands.selectDocEnd) with Shift)
|
||||||
|
- Enter and Shift-Enter: [`insertNewlineAndIndent`](https://codemirror.net/6/docs/ref/#commands.insertNewlineAndIndent)
|
||||||
|
- Ctrl-a (Cmd-a on macOS): [`selectAll`](https://codemirror.net/6/docs/ref/#commands.selectAll)
|
||||||
|
- Backspace: [`deleteCharBackward`](https://codemirror.net/6/docs/ref/#commands.deleteCharBackward)
|
||||||
|
- Delete: [`deleteCharForward`](https://codemirror.net/6/docs/ref/#commands.deleteCharForward)
|
||||||
|
- Ctrl-Backspace (Alt-Backspace on macOS): [`deleteGroupBackward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupBackward)
|
||||||
|
- Ctrl-Delete (Alt-Delete on macOS): [`deleteGroupForward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupForward)
|
||||||
|
- Cmd-Backspace (macOS): [`deleteLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.deleteLineBoundaryBackward).
|
||||||
|
- Cmd-Delete (macOS): [`deleteLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.deleteLineBoundaryForward).
|
||||||
|
*/
|
||||||
|
declare const standardKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
The default keymap. Includes all bindings from
|
||||||
|
[`standardKeymap`](https://codemirror.net/6/docs/ref/#commands.standardKeymap) plus the following:
|
||||||
|
|
||||||
|
- Alt-ArrowLeft (Ctrl-ArrowLeft on macOS): [`cursorSyntaxLeft`](https://codemirror.net/6/docs/ref/#commands.cursorSyntaxLeft) ([`selectSyntaxLeft`](https://codemirror.net/6/docs/ref/#commands.selectSyntaxLeft) with Shift)
|
||||||
|
- Alt-ArrowRight (Ctrl-ArrowRight on macOS): [`cursorSyntaxRight`](https://codemirror.net/6/docs/ref/#commands.cursorSyntaxRight) ([`selectSyntaxRight`](https://codemirror.net/6/docs/ref/#commands.selectSyntaxRight) with Shift)
|
||||||
|
- Alt-ArrowUp: [`moveLineUp`](https://codemirror.net/6/docs/ref/#commands.moveLineUp)
|
||||||
|
- Alt-ArrowDown: [`moveLineDown`](https://codemirror.net/6/docs/ref/#commands.moveLineDown)
|
||||||
|
- Shift-Alt-ArrowUp: [`copyLineUp`](https://codemirror.net/6/docs/ref/#commands.copyLineUp)
|
||||||
|
- Shift-Alt-ArrowDown: [`copyLineDown`](https://codemirror.net/6/docs/ref/#commands.copyLineDown)
|
||||||
|
- Ctrl-Alt-ArrowUp (Cmd-Alt-ArrowUp on macOS): [`addCursorAbove`](https://codemirror.net/6/docs/ref/#commands.addCursorAbove).
|
||||||
|
- Ctrl-Alt-ArrowDown (Cmd-Alt-ArrowDown on macOS): [`addCursorBelow`](https://codemirror.net/6/docs/ref/#commands.addCursorBelow).
|
||||||
|
- Escape: [`simplifySelection`](https://codemirror.net/6/docs/ref/#commands.simplifySelection)
|
||||||
|
- Ctrl-Enter (Cmd-Enter on macOS): [`insertBlankLine`](https://codemirror.net/6/docs/ref/#commands.insertBlankLine)
|
||||||
|
- Alt-l (Ctrl-l on macOS): [`selectLine`](https://codemirror.net/6/docs/ref/#commands.selectLine)
|
||||||
|
- Ctrl-i (Cmd-i on macOS): [`selectParentSyntax`](https://codemirror.net/6/docs/ref/#commands.selectParentSyntax)
|
||||||
|
- Ctrl-[ (Cmd-[ on macOS): [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess)
|
||||||
|
- Ctrl-] (Cmd-] on macOS): [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore)
|
||||||
|
- Ctrl-Alt-\\ (Cmd-Alt-\\ on macOS): [`indentSelection`](https://codemirror.net/6/docs/ref/#commands.indentSelection)
|
||||||
|
- Shift-Ctrl-k (Shift-Cmd-k on macOS): [`deleteLine`](https://codemirror.net/6/docs/ref/#commands.deleteLine)
|
||||||
|
- Shift-Ctrl-\\ (Shift-Cmd-\\ on macOS): [`cursorMatchingBracket`](https://codemirror.net/6/docs/ref/#commands.cursorMatchingBracket)
|
||||||
|
- Ctrl-/ (Cmd-/ on macOS): [`toggleComment`](https://codemirror.net/6/docs/ref/#commands.toggleComment).
|
||||||
|
- Shift-Alt-a: [`toggleBlockComment`](https://codemirror.net/6/docs/ref/#commands.toggleBlockComment).
|
||||||
|
- Ctrl-m (Alt-Shift-m on macOS): [`toggleTabFocusMode`](https://codemirror.net/6/docs/ref/#commands.toggleTabFocusMode).
|
||||||
|
*/
|
||||||
|
declare const defaultKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
A binding that binds Tab to [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) and
|
||||||
|
Shift-Tab to [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess).
|
||||||
|
Please see the [Tab example](../../examples/tab/) before using
|
||||||
|
this.
|
||||||
|
*/
|
||||||
|
declare const indentWithTab: KeyBinding;
|
||||||
|
|
||||||
|
export { type CommentTokens, addCursorAbove, addCursorBelow, blockComment, blockUncomment, copyLineDown, copyLineUp, cursorCharBackward, cursorCharBackwardLogical, cursorCharForward, cursorCharForwardLogical, cursorCharLeft, cursorCharRight, cursorDocEnd, cursorDocStart, cursorGroupBackward, cursorGroupForward, cursorGroupForwardWin, cursorGroupLeft, cursorGroupRight, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorLineBoundaryLeft, cursorLineBoundaryRight, cursorLineDown, cursorLineEnd, cursorLineStart, cursorLineUp, cursorMatchingBracket, cursorPageDown, cursorPageUp, cursorSubwordBackward, cursorSubwordForward, cursorSyntaxLeft, cursorSyntaxRight, defaultKeymap, deleteCharBackward, deleteCharBackwardStrict, deleteCharForward, deleteGroupBackward, deleteGroupForward, deleteGroupForwardWin, deleteLine, deleteLineBoundaryBackward, deleteLineBoundaryForward, deleteToLineEnd, deleteToLineStart, deleteTrailingWhitespace, emacsStyleKeymap, history, historyField, historyKeymap, indentLess, indentMore, indentSelection, indentWithTab, insertBlankLine, insertNewline, insertNewlineAndIndent, insertNewlineKeepIndent, insertTab, invertedEffects, isolateHistory, lineComment, lineUncomment, moveLineDown, moveLineUp, redo, redoDepth, redoSelection, selectAll, selectCharBackward, selectCharBackwardLogical, selectCharForward, selectCharForwardLogical, selectCharLeft, selectCharRight, selectDocEnd, selectDocStart, selectGroupBackward, selectGroupForward, selectGroupForwardWin, selectGroupLeft, selectGroupRight, selectLine, selectLineBoundaryBackward, selectLineBoundaryForward, selectLineBoundaryLeft, selectLineBoundaryRight, selectLineDown, selectLineEnd, selectLineStart, selectLineUp, selectMatchingBracket, selectPageDown, selectPageUp, selectParentSyntax, selectSubwordBackward, selectSubwordForward, selectSyntaxLeft, selectSyntaxRight, simplifySelection, splitLine, standardKeymap, temporarilySetTabFocusMode, toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment, toggleTabFocusMode, transposeChars, undo, undoDepth, undoSelection };
|
||||||
650
editor/node_modules/@codemirror/commands/dist/index.d.ts
generated
vendored
Normal file
650
editor/node_modules/@codemirror/commands/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,650 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { StateCommand, Facet, Transaction, StateEffect, Extension, StateField, EditorState } from '@codemirror/state';
|
||||||
|
import { KeyBinding, Command } from '@codemirror/view';
|
||||||
|
|
||||||
|
/**
|
||||||
|
An object of this type can be provided as [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) under a `"commentTokens"`
|
||||||
|
property to configure comment syntax for a language.
|
||||||
|
*/
|
||||||
|
interface CommentTokens {
|
||||||
|
/**
|
||||||
|
The block comment syntax, if any. For example, for HTML
|
||||||
|
you'd provide `{open: "<!--", close: "-->"}`.
|
||||||
|
*/
|
||||||
|
block?: {
|
||||||
|
open: string;
|
||||||
|
close: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
The line comment syntax. For example `"//"`.
|
||||||
|
*/
|
||||||
|
line?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Comment or uncomment the current selection. Will use line comments
|
||||||
|
if available, otherwise falling back to block comments.
|
||||||
|
*/
|
||||||
|
declare const toggleComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment or uncomment the current selection using line comments.
|
||||||
|
The line comment syntax is taken from the
|
||||||
|
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||||
|
*/
|
||||||
|
declare const toggleLineComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment the current selection using line comments.
|
||||||
|
*/
|
||||||
|
declare const lineComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Uncomment the current selection using line comments.
|
||||||
|
*/
|
||||||
|
declare const lineUncomment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment or uncomment the current selection using block comments.
|
||||||
|
The block comment syntax is taken from the
|
||||||
|
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||||
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||||
|
*/
|
||||||
|
declare const toggleBlockComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment the current selection using block comments.
|
||||||
|
*/
|
||||||
|
declare const blockComment: StateCommand;
|
||||||
|
/**
|
||||||
|
Uncomment the current selection using block comments.
|
||||||
|
*/
|
||||||
|
declare const blockUncomment: StateCommand;
|
||||||
|
/**
|
||||||
|
Comment or uncomment the lines around the current selection using
|
||||||
|
block comments.
|
||||||
|
*/
|
||||||
|
declare const toggleBlockCommentByLine: StateCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Transaction annotation that will prevent that transaction from
|
||||||
|
being combined with other transactions in the undo history. Given
|
||||||
|
`"before"`, it'll prevent merging with previous transactions. With
|
||||||
|
`"after"`, subsequent transactions won't be combined with this
|
||||||
|
one. With `"full"`, the transaction is isolated on both sides.
|
||||||
|
*/
|
||||||
|
declare const isolateHistory: _codemirror_state.AnnotationType<"after" | "before" | "full">;
|
||||||
|
/**
|
||||||
|
This facet provides a way to register functions that, given a
|
||||||
|
transaction, provide a set of effects that the history should
|
||||||
|
store when inverting the transaction. This can be used to
|
||||||
|
integrate some kinds of effects in the history, so that they can
|
||||||
|
be undone (and redone again).
|
||||||
|
*/
|
||||||
|
declare const invertedEffects: Facet<(tr: Transaction) => readonly StateEffect<any>[], readonly ((tr: Transaction) => readonly StateEffect<any>[])[]>;
|
||||||
|
interface HistoryConfig {
|
||||||
|
/**
|
||||||
|
The minimum depth (amount of events) to store. Defaults to 100.
|
||||||
|
*/
|
||||||
|
minDepth?: number;
|
||||||
|
/**
|
||||||
|
The maximum time (in milliseconds) that adjacent events can be
|
||||||
|
apart and still be grouped together. Defaults to 500.
|
||||||
|
*/
|
||||||
|
newGroupDelay?: number;
|
||||||
|
/**
|
||||||
|
By default, when close enough together in time, changes are
|
||||||
|
joined into an existing undo event if they touch any of the
|
||||||
|
changed ranges from that event. You can pass a custom predicate
|
||||||
|
here to influence that logic.
|
||||||
|
*/
|
||||||
|
joinToEvent?: (tr: Transaction, isAdjacent: boolean) => boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Create a history extension with the given configuration.
|
||||||
|
*/
|
||||||
|
declare function history(config?: HistoryConfig): Extension;
|
||||||
|
/**
|
||||||
|
The state field used to store the history data. Should probably
|
||||||
|
only be used when you want to
|
||||||
|
[serialize](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) or
|
||||||
|
[deserialize](https://codemirror.net/6/docs/ref/#state.EditorState^fromJSON) state objects in a way
|
||||||
|
that preserves history.
|
||||||
|
*/
|
||||||
|
declare const historyField: StateField<unknown>;
|
||||||
|
/**
|
||||||
|
Undo a single group of history events. Returns false if no group
|
||||||
|
was available.
|
||||||
|
*/
|
||||||
|
declare const undo: StateCommand;
|
||||||
|
/**
|
||||||
|
Redo a group of history events. Returns false if no group was
|
||||||
|
available.
|
||||||
|
*/
|
||||||
|
declare const redo: StateCommand;
|
||||||
|
/**
|
||||||
|
Undo a change or selection change.
|
||||||
|
*/
|
||||||
|
declare const undoSelection: StateCommand;
|
||||||
|
/**
|
||||||
|
Redo a change or selection change.
|
||||||
|
*/
|
||||||
|
declare const redoSelection: StateCommand;
|
||||||
|
/**
|
||||||
|
The amount of undoable change events available in a given state.
|
||||||
|
*/
|
||||||
|
declare const undoDepth: (state: EditorState) => number;
|
||||||
|
/**
|
||||||
|
The amount of redoable change events available in a given state.
|
||||||
|
*/
|
||||||
|
declare const redoDepth: (state: EditorState) => number;
|
||||||
|
/**
|
||||||
|
Default key bindings for the undo history.
|
||||||
|
|
||||||
|
- Mod-z: [`undo`](https://codemirror.net/6/docs/ref/#commands.undo).
|
||||||
|
- Mod-y (Mod-Shift-z on macOS) + Ctrl-Shift-z on Linux: [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||||
|
- Mod-u: [`undoSelection`](https://codemirror.net/6/docs/ref/#commands.undoSelection).
|
||||||
|
- Alt-u (Mod-Shift-u on macOS): [`redoSelection`](https://codemirror.net/6/docs/ref/#commands.redoSelection).
|
||||||
|
*/
|
||||||
|
declare const historyKeymap: readonly KeyBinding[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
Move the selection one character to the left (which is backward in
|
||||||
|
left-to-right text, forward in right-to-left text).
|
||||||
|
*/
|
||||||
|
declare const cursorCharLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorCharRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character forward.
|
||||||
|
*/
|
||||||
|
declare const cursorCharForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character backward.
|
||||||
|
*/
|
||||||
|
declare const cursorCharBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one character forward, in logical
|
||||||
|
(non-text-direction-aware) string index order.
|
||||||
|
*/
|
||||||
|
declare const cursorCharForwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection one character backward, in logical string index
|
||||||
|
order.
|
||||||
|
*/
|
||||||
|
declare const cursorCharBackwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection to the left across one group of word or
|
||||||
|
non-word (but also non-space) characters.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group forward.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group backward.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the cursor one group forward in the default Windows style,
|
||||||
|
where it moves to the start of the next group.
|
||||||
|
*/
|
||||||
|
declare const cursorGroupForwardWin: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group or camel-case subword forward.
|
||||||
|
*/
|
||||||
|
declare const cursorSubwordForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one group or camel-case subword backward.
|
||||||
|
*/
|
||||||
|
declare const cursorSubwordBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the cursor over the next syntactic element to the left.
|
||||||
|
*/
|
||||||
|
declare const cursorSyntaxLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the cursor over the next syntactic element to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorSyntaxRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line up.
|
||||||
|
*/
|
||||||
|
declare const cursorLineUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line down.
|
||||||
|
*/
|
||||||
|
declare const cursorLineDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one page up.
|
||||||
|
*/
|
||||||
|
declare const cursorPageUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one page down.
|
||||||
|
*/
|
||||||
|
declare const cursorPageDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the next line wrap point, or to the end of
|
||||||
|
the line if there isn't one left on this line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to previous line wrap point, or failing that to
|
||||||
|
the start of the line. If the line is indented, and the cursor
|
||||||
|
isn't already at the end of the indentation, this will move to the
|
||||||
|
end of the indentation instead of the start of the line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line wrap point to the left.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection one line wrap point to the right.
|
||||||
|
*/
|
||||||
|
declare const cursorLineBoundaryRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the start of the line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineStart: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the end of the line.
|
||||||
|
*/
|
||||||
|
declare const cursorLineEnd: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the bracket matching the one it is currently
|
||||||
|
on, if any.
|
||||||
|
*/
|
||||||
|
declare const cursorMatchingBracket: StateCommand;
|
||||||
|
/**
|
||||||
|
Extend the selection to the bracket matching the one the selection
|
||||||
|
head is currently on, if any.
|
||||||
|
*/
|
||||||
|
declare const selectMatchingBracket: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head one character to the left, while leaving
|
||||||
|
the anchor in place.
|
||||||
|
*/
|
||||||
|
declare const selectCharLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character to the right.
|
||||||
|
*/
|
||||||
|
declare const selectCharRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character forward.
|
||||||
|
*/
|
||||||
|
declare const selectCharForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character backward.
|
||||||
|
*/
|
||||||
|
declare const selectCharBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one character forward by logical
|
||||||
|
(non-direction aware) string index order.
|
||||||
|
*/
|
||||||
|
declare const selectCharForwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head one character backward by logical string
|
||||||
|
index order.
|
||||||
|
*/
|
||||||
|
declare const selectCharBackwardLogical: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head one [group](https://codemirror.net/6/docs/ref/#commands.cursorGroupLeft) to
|
||||||
|
the left.
|
||||||
|
*/
|
||||||
|
declare const selectGroupLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group to the right.
|
||||||
|
*/
|
||||||
|
declare const selectGroupRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group forward.
|
||||||
|
*/
|
||||||
|
declare const selectGroupForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group backward.
|
||||||
|
*/
|
||||||
|
declare const selectGroupBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group forward in the default Windows
|
||||||
|
style, skipping to the start of the next group.
|
||||||
|
*/
|
||||||
|
declare const selectGroupForwardWin: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group or camel-case subword forward.
|
||||||
|
*/
|
||||||
|
declare const selectSubwordForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one group or subword backward.
|
||||||
|
*/
|
||||||
|
declare const selectSubwordBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head over the next syntactic element to the left.
|
||||||
|
*/
|
||||||
|
declare const selectSyntaxLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head over the next syntactic element to the right.
|
||||||
|
*/
|
||||||
|
declare const selectSyntaxRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line up.
|
||||||
|
*/
|
||||||
|
declare const selectLineUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line down.
|
||||||
|
*/
|
||||||
|
declare const selectLineDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one page up.
|
||||||
|
*/
|
||||||
|
declare const selectPageUp: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one page down.
|
||||||
|
*/
|
||||||
|
declare const selectPageDown: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the next line boundary.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryForward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the previous line boundary.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryBackward: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line boundary to the left.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryLeft: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head one line boundary to the right.
|
||||||
|
*/
|
||||||
|
declare const selectLineBoundaryRight: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the start of the line.
|
||||||
|
*/
|
||||||
|
declare const selectLineStart: Command;
|
||||||
|
/**
|
||||||
|
Move the selection head to the end of the line.
|
||||||
|
*/
|
||||||
|
declare const selectLineEnd: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the start of the document.
|
||||||
|
*/
|
||||||
|
declare const cursorDocStart: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection to the end of the document.
|
||||||
|
*/
|
||||||
|
declare const cursorDocEnd: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head to the start of the document.
|
||||||
|
*/
|
||||||
|
declare const selectDocStart: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selection head to the end of the document.
|
||||||
|
*/
|
||||||
|
declare const selectDocEnd: StateCommand;
|
||||||
|
/**
|
||||||
|
Select the entire document.
|
||||||
|
*/
|
||||||
|
declare const selectAll: StateCommand;
|
||||||
|
/**
|
||||||
|
Expand the selection to cover entire lines.
|
||||||
|
*/
|
||||||
|
declare const selectLine: StateCommand;
|
||||||
|
/**
|
||||||
|
Select the next syntactic construct that is larger than the
|
||||||
|
selection. Note that this will only work insofar as the language
|
||||||
|
[provider](https://codemirror.net/6/docs/ref/#language.language) you use builds up a full
|
||||||
|
syntax tree.
|
||||||
|
*/
|
||||||
|
declare const selectParentSyntax: StateCommand;
|
||||||
|
/**
|
||||||
|
Expand the selection by adding a cursor above the heads of
|
||||||
|
currently selected ranges.
|
||||||
|
*/
|
||||||
|
declare const addCursorAbove: Command;
|
||||||
|
/**
|
||||||
|
Expand the selection by adding a cursor below the heads of
|
||||||
|
currently selected ranges.
|
||||||
|
*/
|
||||||
|
declare const addCursorBelow: Command;
|
||||||
|
/**
|
||||||
|
Simplify the current selection. When multiple ranges are selected,
|
||||||
|
reduce it to its main range. Otherwise, if the selection is
|
||||||
|
non-empty, convert it to a cursor selection.
|
||||||
|
*/
|
||||||
|
declare const simplifySelection: StateCommand;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, for cursor selections, the character or
|
||||||
|
indentation unit before the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteCharBackward: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection or the character before the cursor. Does not
|
||||||
|
implement any extended behavior like deleting whole indentation
|
||||||
|
units in one go.
|
||||||
|
*/
|
||||||
|
declare const deleteCharBackwardStrict: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection or the character after the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteCharForward: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection or backward until the end of the next
|
||||||
|
[group](https://codemirror.net/6/docs/ref/#view.EditorView.moveByGroup), only skipping groups of
|
||||||
|
whitespace when they consist of a single space.
|
||||||
|
*/
|
||||||
|
declare const deleteGroupBackward: StateCommand;
|
||||||
|
/**
|
||||||
|
Delete the selection or forward until the end of the next group.
|
||||||
|
*/
|
||||||
|
declare const deleteGroupForward: StateCommand;
|
||||||
|
/**
|
||||||
|
Variant of [`deleteGroupForward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupForward)
|
||||||
|
that uses the Windows convention of also deleting the whitespace
|
||||||
|
after a word.
|
||||||
|
*/
|
||||||
|
declare const deleteGroupForwardWin: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the end of the line. If the cursor is directly at the end of the
|
||||||
|
line, delete the line break after it.
|
||||||
|
*/
|
||||||
|
declare const deleteToLineEnd: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the start of the line. If the cursor is directly at the start of the
|
||||||
|
line, delete the line break before it.
|
||||||
|
*/
|
||||||
|
declare const deleteToLineStart: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the start of the line or the next line wrap before the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteLineBoundaryBackward: Command;
|
||||||
|
/**
|
||||||
|
Delete the selection, or, if it is a cursor selection, delete to
|
||||||
|
the end of the line or the next line wrap after the cursor.
|
||||||
|
*/
|
||||||
|
declare const deleteLineBoundaryForward: Command;
|
||||||
|
/**
|
||||||
|
Delete all whitespace directly before a line end from the
|
||||||
|
document.
|
||||||
|
*/
|
||||||
|
declare const deleteTrailingWhitespace: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace each selection range with a line break, leaving the cursor
|
||||||
|
on the line before the break.
|
||||||
|
*/
|
||||||
|
declare const splitLine: StateCommand;
|
||||||
|
/**
|
||||||
|
Flip the characters before and after the cursor(s).
|
||||||
|
*/
|
||||||
|
declare const transposeChars: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selected lines up one line.
|
||||||
|
*/
|
||||||
|
declare const moveLineUp: StateCommand;
|
||||||
|
/**
|
||||||
|
Move the selected lines down one line.
|
||||||
|
*/
|
||||||
|
declare const moveLineDown: StateCommand;
|
||||||
|
/**
|
||||||
|
Create a copy of the selected lines. Keep the selection in the top copy.
|
||||||
|
*/
|
||||||
|
declare const copyLineUp: StateCommand;
|
||||||
|
/**
|
||||||
|
Create a copy of the selected lines. Keep the selection in the bottom copy.
|
||||||
|
*/
|
||||||
|
declare const copyLineDown: StateCommand;
|
||||||
|
/**
|
||||||
|
Delete selected lines.
|
||||||
|
*/
|
||||||
|
declare const deleteLine: Command;
|
||||||
|
/**
|
||||||
|
Replace the selection with a newline.
|
||||||
|
*/
|
||||||
|
declare const insertNewline: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace the selection with a newline and the same amount of
|
||||||
|
indentation as the line above.
|
||||||
|
*/
|
||||||
|
declare const insertNewlineKeepIndent: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace the selection with a newline and indent the newly created
|
||||||
|
line(s). If the current line consists only of whitespace, this
|
||||||
|
will also delete that whitespace. When the cursor is between
|
||||||
|
matching brackets, an additional newline will be inserted after
|
||||||
|
the cursor.
|
||||||
|
*/
|
||||||
|
declare const insertNewlineAndIndent: StateCommand;
|
||||||
|
/**
|
||||||
|
Create a blank, indented line below the current line.
|
||||||
|
*/
|
||||||
|
declare const insertBlankLine: StateCommand;
|
||||||
|
/**
|
||||||
|
Auto-indent the selected lines. This uses the [indentation service
|
||||||
|
facet](https://codemirror.net/6/docs/ref/#language.indentService) as source for auto-indent
|
||||||
|
information.
|
||||||
|
*/
|
||||||
|
declare const indentSelection: StateCommand;
|
||||||
|
/**
|
||||||
|
Add a [unit](https://codemirror.net/6/docs/ref/#language.indentUnit) of indentation to all selected
|
||||||
|
lines.
|
||||||
|
*/
|
||||||
|
declare const indentMore: StateCommand;
|
||||||
|
/**
|
||||||
|
Remove a [unit](https://codemirror.net/6/docs/ref/#language.indentUnit) of indentation from all
|
||||||
|
selected lines.
|
||||||
|
*/
|
||||||
|
declare const indentLess: StateCommand;
|
||||||
|
/**
|
||||||
|
Enables or disables
|
||||||
|
[tab-focus mode](https://codemirror.net/6/docs/ref/#view.EditorView.setTabFocusMode). While on, this
|
||||||
|
prevents the editor's key bindings from capturing Tab or
|
||||||
|
Shift-Tab, making it possible for the user to move focus out of
|
||||||
|
the editor with the keyboard.
|
||||||
|
*/
|
||||||
|
declare const toggleTabFocusMode: Command;
|
||||||
|
/**
|
||||||
|
Temporarily enables [tab-focus
|
||||||
|
mode](https://codemirror.net/6/docs/ref/#view.EditorView.setTabFocusMode) for two seconds or until
|
||||||
|
another key is pressed.
|
||||||
|
*/
|
||||||
|
declare const temporarilySetTabFocusMode: Command;
|
||||||
|
/**
|
||||||
|
Insert a tab character at the cursor or, if something is selected,
|
||||||
|
use [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) to indent the entire
|
||||||
|
selection.
|
||||||
|
*/
|
||||||
|
declare const insertTab: StateCommand;
|
||||||
|
/**
|
||||||
|
Array of key bindings containing the Emacs-style bindings that are
|
||||||
|
available on macOS by default.
|
||||||
|
|
||||||
|
- Ctrl-b: [`cursorCharLeft`](https://codemirror.net/6/docs/ref/#commands.cursorCharLeft) ([`selectCharLeft`](https://codemirror.net/6/docs/ref/#commands.selectCharLeft) with Shift)
|
||||||
|
- Ctrl-f: [`cursorCharRight`](https://codemirror.net/6/docs/ref/#commands.cursorCharRight) ([`selectCharRight`](https://codemirror.net/6/docs/ref/#commands.selectCharRight) with Shift)
|
||||||
|
- Ctrl-p: [`cursorLineUp`](https://codemirror.net/6/docs/ref/#commands.cursorLineUp) ([`selectLineUp`](https://codemirror.net/6/docs/ref/#commands.selectLineUp) with Shift)
|
||||||
|
- Ctrl-n: [`cursorLineDown`](https://codemirror.net/6/docs/ref/#commands.cursorLineDown) ([`selectLineDown`](https://codemirror.net/6/docs/ref/#commands.selectLineDown) with Shift)
|
||||||
|
- Ctrl-a: [`cursorLineStart`](https://codemirror.net/6/docs/ref/#commands.cursorLineStart) ([`selectLineStart`](https://codemirror.net/6/docs/ref/#commands.selectLineStart) with Shift)
|
||||||
|
- Ctrl-e: [`cursorLineEnd`](https://codemirror.net/6/docs/ref/#commands.cursorLineEnd) ([`selectLineEnd`](https://codemirror.net/6/docs/ref/#commands.selectLineEnd) with Shift)
|
||||||
|
- Ctrl-d: [`deleteCharForward`](https://codemirror.net/6/docs/ref/#commands.deleteCharForward)
|
||||||
|
- Ctrl-h: [`deleteCharBackward`](https://codemirror.net/6/docs/ref/#commands.deleteCharBackward)
|
||||||
|
- Ctrl-k: [`deleteToLineEnd`](https://codemirror.net/6/docs/ref/#commands.deleteToLineEnd)
|
||||||
|
- Ctrl-Alt-h: [`deleteGroupBackward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupBackward)
|
||||||
|
- Ctrl-o: [`splitLine`](https://codemirror.net/6/docs/ref/#commands.splitLine)
|
||||||
|
- Ctrl-t: [`transposeChars`](https://codemirror.net/6/docs/ref/#commands.transposeChars)
|
||||||
|
- Ctrl-v: [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown)
|
||||||
|
- Alt-v: [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp)
|
||||||
|
*/
|
||||||
|
declare const emacsStyleKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
An array of key bindings closely sticking to platform-standard or
|
||||||
|
widely used bindings. (This includes the bindings from
|
||||||
|
[`emacsStyleKeymap`](https://codemirror.net/6/docs/ref/#commands.emacsStyleKeymap), with their `key`
|
||||||
|
property changed to `mac`.)
|
||||||
|
|
||||||
|
- ArrowLeft: [`cursorCharLeft`](https://codemirror.net/6/docs/ref/#commands.cursorCharLeft) ([`selectCharLeft`](https://codemirror.net/6/docs/ref/#commands.selectCharLeft) with Shift)
|
||||||
|
- ArrowRight: [`cursorCharRight`](https://codemirror.net/6/docs/ref/#commands.cursorCharRight) ([`selectCharRight`](https://codemirror.net/6/docs/ref/#commands.selectCharRight) with Shift)
|
||||||
|
- Ctrl-ArrowLeft (Alt-ArrowLeft on macOS): [`cursorGroupLeft`](https://codemirror.net/6/docs/ref/#commands.cursorGroupLeft) ([`selectGroupLeft`](https://codemirror.net/6/docs/ref/#commands.selectGroupLeft) with Shift)
|
||||||
|
- Ctrl-ArrowRight (Alt-ArrowRight on macOS): [`cursorGroupRight`](https://codemirror.net/6/docs/ref/#commands.cursorGroupRight) ([`selectGroupRight`](https://codemirror.net/6/docs/ref/#commands.selectGroupRight) with Shift)
|
||||||
|
- Cmd-ArrowLeft (on macOS): [`cursorLineStart`](https://codemirror.net/6/docs/ref/#commands.cursorLineStart) ([`selectLineStart`](https://codemirror.net/6/docs/ref/#commands.selectLineStart) with Shift)
|
||||||
|
- Cmd-ArrowRight (on macOS): [`cursorLineEnd`](https://codemirror.net/6/docs/ref/#commands.cursorLineEnd) ([`selectLineEnd`](https://codemirror.net/6/docs/ref/#commands.selectLineEnd) with Shift)
|
||||||
|
- ArrowUp: [`cursorLineUp`](https://codemirror.net/6/docs/ref/#commands.cursorLineUp) ([`selectLineUp`](https://codemirror.net/6/docs/ref/#commands.selectLineUp) with Shift)
|
||||||
|
- ArrowDown: [`cursorLineDown`](https://codemirror.net/6/docs/ref/#commands.cursorLineDown) ([`selectLineDown`](https://codemirror.net/6/docs/ref/#commands.selectLineDown) with Shift)
|
||||||
|
- Cmd-ArrowUp (on macOS): [`cursorDocStart`](https://codemirror.net/6/docs/ref/#commands.cursorDocStart) ([`selectDocStart`](https://codemirror.net/6/docs/ref/#commands.selectDocStart) with Shift)
|
||||||
|
- Cmd-ArrowDown (on macOS): [`cursorDocEnd`](https://codemirror.net/6/docs/ref/#commands.cursorDocEnd) ([`selectDocEnd`](https://codemirror.net/6/docs/ref/#commands.selectDocEnd) with Shift)
|
||||||
|
- Ctrl-ArrowUp (on macOS): [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp) ([`selectPageUp`](https://codemirror.net/6/docs/ref/#commands.selectPageUp) with Shift)
|
||||||
|
- Ctrl-ArrowDown (on macOS): [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown) ([`selectPageDown`](https://codemirror.net/6/docs/ref/#commands.selectPageDown) with Shift)
|
||||||
|
- PageUp: [`cursorPageUp`](https://codemirror.net/6/docs/ref/#commands.cursorPageUp) ([`selectPageUp`](https://codemirror.net/6/docs/ref/#commands.selectPageUp) with Shift)
|
||||||
|
- PageDown: [`cursorPageDown`](https://codemirror.net/6/docs/ref/#commands.cursorPageDown) ([`selectPageDown`](https://codemirror.net/6/docs/ref/#commands.selectPageDown) with Shift)
|
||||||
|
- Home: [`cursorLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.cursorLineBoundaryBackward) ([`selectLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.selectLineBoundaryBackward) with Shift)
|
||||||
|
- End: [`cursorLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.cursorLineBoundaryForward) ([`selectLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.selectLineBoundaryForward) with Shift)
|
||||||
|
- Ctrl-Home (Cmd-Home on macOS): [`cursorDocStart`](https://codemirror.net/6/docs/ref/#commands.cursorDocStart) ([`selectDocStart`](https://codemirror.net/6/docs/ref/#commands.selectDocStart) with Shift)
|
||||||
|
- Ctrl-End (Cmd-Home on macOS): [`cursorDocEnd`](https://codemirror.net/6/docs/ref/#commands.cursorDocEnd) ([`selectDocEnd`](https://codemirror.net/6/docs/ref/#commands.selectDocEnd) with Shift)
|
||||||
|
- Enter and Shift-Enter: [`insertNewlineAndIndent`](https://codemirror.net/6/docs/ref/#commands.insertNewlineAndIndent)
|
||||||
|
- Ctrl-a (Cmd-a on macOS): [`selectAll`](https://codemirror.net/6/docs/ref/#commands.selectAll)
|
||||||
|
- Backspace: [`deleteCharBackward`](https://codemirror.net/6/docs/ref/#commands.deleteCharBackward)
|
||||||
|
- Delete: [`deleteCharForward`](https://codemirror.net/6/docs/ref/#commands.deleteCharForward)
|
||||||
|
- Ctrl-Backspace (Alt-Backspace on macOS): [`deleteGroupBackward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupBackward)
|
||||||
|
- Ctrl-Delete (Alt-Delete on macOS): [`deleteGroupForward`](https://codemirror.net/6/docs/ref/#commands.deleteGroupForward)
|
||||||
|
- Cmd-Backspace (macOS): [`deleteLineBoundaryBackward`](https://codemirror.net/6/docs/ref/#commands.deleteLineBoundaryBackward).
|
||||||
|
- Cmd-Delete (macOS): [`deleteLineBoundaryForward`](https://codemirror.net/6/docs/ref/#commands.deleteLineBoundaryForward).
|
||||||
|
*/
|
||||||
|
declare const standardKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
The default keymap. Includes all bindings from
|
||||||
|
[`standardKeymap`](https://codemirror.net/6/docs/ref/#commands.standardKeymap) plus the following:
|
||||||
|
|
||||||
|
- Alt-ArrowLeft (Ctrl-ArrowLeft on macOS): [`cursorSyntaxLeft`](https://codemirror.net/6/docs/ref/#commands.cursorSyntaxLeft) ([`selectSyntaxLeft`](https://codemirror.net/6/docs/ref/#commands.selectSyntaxLeft) with Shift)
|
||||||
|
- Alt-ArrowRight (Ctrl-ArrowRight on macOS): [`cursorSyntaxRight`](https://codemirror.net/6/docs/ref/#commands.cursorSyntaxRight) ([`selectSyntaxRight`](https://codemirror.net/6/docs/ref/#commands.selectSyntaxRight) with Shift)
|
||||||
|
- Alt-ArrowUp: [`moveLineUp`](https://codemirror.net/6/docs/ref/#commands.moveLineUp)
|
||||||
|
- Alt-ArrowDown: [`moveLineDown`](https://codemirror.net/6/docs/ref/#commands.moveLineDown)
|
||||||
|
- Shift-Alt-ArrowUp: [`copyLineUp`](https://codemirror.net/6/docs/ref/#commands.copyLineUp)
|
||||||
|
- Shift-Alt-ArrowDown: [`copyLineDown`](https://codemirror.net/6/docs/ref/#commands.copyLineDown)
|
||||||
|
- Ctrl-Alt-ArrowUp (Cmd-Alt-ArrowUp on macOS): [`addCursorAbove`](https://codemirror.net/6/docs/ref/#commands.addCursorAbove).
|
||||||
|
- Ctrl-Alt-ArrowDown (Cmd-Alt-ArrowDown on macOS): [`addCursorBelow`](https://codemirror.net/6/docs/ref/#commands.addCursorBelow).
|
||||||
|
- Escape: [`simplifySelection`](https://codemirror.net/6/docs/ref/#commands.simplifySelection)
|
||||||
|
- Ctrl-Enter (Cmd-Enter on macOS): [`insertBlankLine`](https://codemirror.net/6/docs/ref/#commands.insertBlankLine)
|
||||||
|
- Alt-l (Ctrl-l on macOS): [`selectLine`](https://codemirror.net/6/docs/ref/#commands.selectLine)
|
||||||
|
- Ctrl-i (Cmd-i on macOS): [`selectParentSyntax`](https://codemirror.net/6/docs/ref/#commands.selectParentSyntax)
|
||||||
|
- Ctrl-[ (Cmd-[ on macOS): [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess)
|
||||||
|
- Ctrl-] (Cmd-] on macOS): [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore)
|
||||||
|
- Ctrl-Alt-\\ (Cmd-Alt-\\ on macOS): [`indentSelection`](https://codemirror.net/6/docs/ref/#commands.indentSelection)
|
||||||
|
- Shift-Ctrl-k (Shift-Cmd-k on macOS): [`deleteLine`](https://codemirror.net/6/docs/ref/#commands.deleteLine)
|
||||||
|
- Shift-Ctrl-\\ (Shift-Cmd-\\ on macOS): [`cursorMatchingBracket`](https://codemirror.net/6/docs/ref/#commands.cursorMatchingBracket)
|
||||||
|
- Ctrl-/ (Cmd-/ on macOS): [`toggleComment`](https://codemirror.net/6/docs/ref/#commands.toggleComment).
|
||||||
|
- Shift-Alt-a: [`toggleBlockComment`](https://codemirror.net/6/docs/ref/#commands.toggleBlockComment).
|
||||||
|
- Ctrl-m (Alt-Shift-m on macOS): [`toggleTabFocusMode`](https://codemirror.net/6/docs/ref/#commands.toggleTabFocusMode).
|
||||||
|
*/
|
||||||
|
declare const defaultKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
A binding that binds Tab to [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) and
|
||||||
|
Shift-Tab to [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess).
|
||||||
|
Please see the [Tab example](../../examples/tab/) before using
|
||||||
|
this.
|
||||||
|
*/
|
||||||
|
declare const indentWithTab: KeyBinding;
|
||||||
|
|
||||||
|
export { type CommentTokens, addCursorAbove, addCursorBelow, blockComment, blockUncomment, copyLineDown, copyLineUp, cursorCharBackward, cursorCharBackwardLogical, cursorCharForward, cursorCharForwardLogical, cursorCharLeft, cursorCharRight, cursorDocEnd, cursorDocStart, cursorGroupBackward, cursorGroupForward, cursorGroupForwardWin, cursorGroupLeft, cursorGroupRight, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorLineBoundaryLeft, cursorLineBoundaryRight, cursorLineDown, cursorLineEnd, cursorLineStart, cursorLineUp, cursorMatchingBracket, cursorPageDown, cursorPageUp, cursorSubwordBackward, cursorSubwordForward, cursorSyntaxLeft, cursorSyntaxRight, defaultKeymap, deleteCharBackward, deleteCharBackwardStrict, deleteCharForward, deleteGroupBackward, deleteGroupForward, deleteGroupForwardWin, deleteLine, deleteLineBoundaryBackward, deleteLineBoundaryForward, deleteToLineEnd, deleteToLineStart, deleteTrailingWhitespace, emacsStyleKeymap, history, historyField, historyKeymap, indentLess, indentMore, indentSelection, indentWithTab, insertBlankLine, insertNewline, insertNewlineAndIndent, insertNewlineKeepIndent, insertTab, invertedEffects, isolateHistory, lineComment, lineUncomment, moveLineDown, moveLineUp, redo, redoDepth, redoSelection, selectAll, selectCharBackward, selectCharBackwardLogical, selectCharForward, selectCharForwardLogical, selectCharLeft, selectCharRight, selectDocEnd, selectDocStart, selectGroupBackward, selectGroupForward, selectGroupForwardWin, selectGroupLeft, selectGroupRight, selectLine, selectLineBoundaryBackward, selectLineBoundaryForward, selectLineBoundaryLeft, selectLineBoundaryRight, selectLineDown, selectLineEnd, selectLineStart, selectLineUp, selectMatchingBracket, selectPageDown, selectPageUp, selectParentSyntax, selectSubwordBackward, selectSubwordForward, selectSyntaxLeft, selectSyntaxRight, simplifySelection, splitLine, standardKeymap, temporarilySetTabFocusMode, toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment, toggleTabFocusMode, transposeChars, undo, undoDepth, undoSelection };
|
||||||
1795
editor/node_modules/@codemirror/commands/dist/index.js
generated
vendored
Normal file
1795
editor/node_modules/@codemirror/commands/dist/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
42
editor/node_modules/@codemirror/commands/package.json
generated
vendored
Normal file
42
editor/node_modules/@codemirror/commands/package.json
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "@codemirror/commands",
|
||||||
|
"version": "6.10.3",
|
||||||
|
"description": "Collection of editing commands for the CodeMirror code editor",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cm-runtests",
|
||||||
|
"prepare": "cm-buildhelper src/commands.ts"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"code"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Marijn Haverbeke",
|
||||||
|
"email": "marijn@haverbeke.berlin",
|
||||||
|
"url": "http://marijnhaverbeke.nl"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"sideEffects": false,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.6.0",
|
||||||
|
"@codemirror/view": "^6.27.0",
|
||||||
|
"@lezer/common": "^1.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/buildhelper": "^1.0.0",
|
||||||
|
"@codemirror/lang-javascript": "^6.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/codemirror/commands.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
16
editor/node_modules/@codemirror/language/.github/workflows/dispatch.yml
generated
vendored
Normal file
16
editor/node_modules/@codemirror/language/.github/workflows/dispatch.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Trigger CI
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Dispatch to main repo
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Emit repository_dispatch
|
||||||
|
uses: mvasigh/dispatch-action@main
|
||||||
|
with:
|
||||||
|
# You should create a personal access token and store it in your repository
|
||||||
|
token: ${{ secrets.DISPATCH_AUTH }}
|
||||||
|
repo: dev
|
||||||
|
owner: codemirror
|
||||||
|
event_type: push
|
||||||
412
editor/node_modules/@codemirror/language/CHANGELOG.md
generated
vendored
Normal file
412
editor/node_modules/@codemirror/language/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,412 @@
|
|||||||
|
## 6.12.3 (2026-03-25)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a crash in `bracketMatching` when composing at end of document.
|
||||||
|
|
||||||
|
## 6.12.2 (2026-02-25)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure brackets are highlighted in the initial editor state.
|
||||||
|
|
||||||
|
Pause bracket matching updates during composition, to avoid disrupting Mobile Safari's fragile composition handling.
|
||||||
|
|
||||||
|
## 6.12.1 (2025-12-22)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Improve finding inner language in syntax tree when the nested parse has been marked as bracketed.
|
||||||
|
|
||||||
|
## 6.11.3 (2025-08-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make the stream parser user 4 times smaller chunks to reduce the amount of re-parsed code on changes.
|
||||||
|
|
||||||
|
## 6.11.2 (2025-06-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure folded ranges open when backspacing or deleting into them.
|
||||||
|
|
||||||
|
## 6.11.1 (2025-06-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where indentation would sometimes miss nodes in mixed-language situations.
|
||||||
|
|
||||||
|
## 6.11.0 (2025-03-13)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Stream parsers now support a `mergeTokens` option that can be used to turn off automatic merging of adjacent tokens.
|
||||||
|
|
||||||
|
## 6.10.8 (2024-12-23)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a regression introduced 6.10.7 that caused indention to sometimes crash on nested language boundaries.
|
||||||
|
|
||||||
|
## 6.10.7 (2024-12-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where indentation for a stream language would fail to work when the parse covered only part of the document, far from the start.
|
||||||
|
|
||||||
|
Make sure the inner mode gets a chance to indent when indenting right at the end of a nested language section.
|
||||||
|
|
||||||
|
## 6.10.6 (2024-11-29)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a crash in `StreamLanguage` when the input range is entirely before the editor viewport.
|
||||||
|
|
||||||
|
## 6.10.5 (2024-11-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where a `StreamLanguage` could get confused when trying to reuse existing parse data when the parsed range changed.
|
||||||
|
|
||||||
|
## 6.10.4 (2024-11-24)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Join adjacent tokens of the same type into a single token in .
|
||||||
|
|
||||||
|
Call stream language indent functions even when the language is used as a nested parser.
|
||||||
|
|
||||||
|
Fix a crash in `StreamParser` when a parse was resumed with different input ranges.
|
||||||
|
|
||||||
|
## 6.10.3 (2024-09-19)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a TypeScript error when using `HighlightStyle` with the `exactOptionalPropertyTypes` typechecking option enabled.
|
||||||
|
|
||||||
|
Make `delimitedIndent` align to spaces after the opening token.
|
||||||
|
|
||||||
|
## 6.10.2 (2024-06-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an infinite loop that could occur when enabling `bidiIsolates` in documents with both bidirectional text and very long lines.
|
||||||
|
|
||||||
|
## 6.10.1 (2024-02-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where, when a lot of code is visible in the initial editor, the bottom bit of code is shown without highlighting for one frame.
|
||||||
|
|
||||||
|
## 6.10.0 (2023-12-28)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `bidiIsolates` extension can be used to wrap syntactic elements where this is appropriate in an element that isolates their text direction, avoiding weird ordering of neutral characters on direction boundaries.
|
||||||
|
|
||||||
|
## 6.9.3 (2023-11-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue in `StreamLanguage` where it ran out of node type ids if you repeatedly redefined a language with the same token table.
|
||||||
|
|
||||||
|
## 6.9.2 (2023-10-24)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Allow `StreamParser` tokens get multiple highlighting tags.
|
||||||
|
|
||||||
|
## 6.9.1 (2023-09-20)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Indentation now works a lot better in mixed-language documents that interleave the languages in a complex way.
|
||||||
|
|
||||||
|
Code folding is now able to pick the right foldable syntax node when the line end falls in a mixed-parsing language that doesn't match the target node.
|
||||||
|
|
||||||
|
## 6.9.0 (2023-08-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `getIndentation` return null, rather than 0, when there is no syntax tree available.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `preparePlaceholder` option to `codeFolding` makes it possible to display contextual information in a folded range placeholder widget.
|
||||||
|
|
||||||
|
## 6.8.0 (2023-06-12)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `baseIndentFor` method in `TreeIndentContext` can be used to find the base indentation for an arbitrary node.
|
||||||
|
|
||||||
|
## 6.7.0 (2023-05-19)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Export `DocInput` class for feeding editor documents to a Lezer parser.
|
||||||
|
|
||||||
|
## 6.6.0 (2023-02-13)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Syntax-driven language data queries now support sublanguages, which make it possible to return different data for specific parts of the tree produced by a single language.
|
||||||
|
|
||||||
|
## 6.5.0 (2023-02-07)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make indentation for stream languages more reliable by having `StringStream.indentation` return overridden indentations from the indent context.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `toggleFold` command folds or unfolds depending on whether there's an existing folded range on the current line.
|
||||||
|
|
||||||
|
`indentUnit` now accepts any (repeated) whitespace character, not just spaces and tabs.
|
||||||
|
|
||||||
|
## 6.4.0 (2023-01-12)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `bracketMatchingHandle` node prop can now be used to limit bracket matching behavior for larger nodes to a single subnode (for example the tag name of an HTML tag).
|
||||||
|
|
||||||
|
## 6.3.2 (2022-12-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused `ensureSyntaxTree` to return incomplete trees when using a viewport-aware parser like `StreamLanguage`.
|
||||||
|
|
||||||
|
## 6.3.1 (2022-11-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make syntax-based folding include syntax nodes that start right at the end of a line as potential fold targets.
|
||||||
|
|
||||||
|
Fix the `indentService` protocol to allow a distinction between declining to handle the indentation and returning null to indicate the line has no definite indentation.
|
||||||
|
|
||||||
|
## 6.3.0 (2022-10-24)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`HighlightStyle` objects now have a `specs` property holding the tag styles that were used to define them.
|
||||||
|
|
||||||
|
`Language` objects now have a `name` field holding the language name.
|
||||||
|
|
||||||
|
## 6.2.1 (2022-07-21)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where `bracketMatching` would incorrectly match nested brackets in syntax trees that put multiple pairs of brackets in the same parent node.
|
||||||
|
|
||||||
|
Fix a bug that could cause `indentRange` to loop infinitely.
|
||||||
|
|
||||||
|
## 6.2.0 (2022-06-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that prevented bracket matching to recognize plain brackets inside a language parsed as an overlay.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `indentRange` function provides an easy way to programatically auto-indent a range of the document.
|
||||||
|
|
||||||
|
## 6.1.0 (2022-06-20)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `foldState` field is now public, and can be used to serialize and deserialize the fold state.
|
||||||
|
|
||||||
|
## 6.0.0 (2022-06-08)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `foldingChanged` option to `foldGutter` can now be used to trigger a recomputation of the fold markers.
|
||||||
|
|
||||||
|
## 0.20.2 (2022-05-20)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
List style-mod as a dependency.
|
||||||
|
|
||||||
|
## 0.20.1 (2022-05-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure `all` styles in the CSS generated for a `HighlightStyle` have a lower precedence than the other rules defined for the style. Use a shorthand property
|
||||||
|
|
||||||
|
## 0.20.0 (2022-04-20)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
`HighlightStyle.get` is now called `highlightingFor`.
|
||||||
|
|
||||||
|
`HighlightStyles` no longer function as extensions (to improve tree shaking), and must be wrapped with `syntaxHighlighting` to add to an editor configuration.
|
||||||
|
|
||||||
|
`Language` objects no longer have a `topNode` property.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`HighlightStyle` and `defaultHighlightStyle` from the now-removed @codemirror/highlight package now live in this package.
|
||||||
|
|
||||||
|
The new `forceParsing` function can be used to run the parser forward on an editor view.
|
||||||
|
|
||||||
|
The exports that used to live in @codemirror/matchbrackets are now exported from this package.
|
||||||
|
|
||||||
|
The @codemirror/fold package has been merged into this one.
|
||||||
|
|
||||||
|
The exports from the old @codemirror/stream-parser package now live in this package.
|
||||||
|
|
||||||
|
## 0.19.10 (2022-03-31)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Autocompletion may now also trigger automatic indentation on input.
|
||||||
|
|
||||||
|
## 0.19.9 (2022-03-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure nodes that end at the end of a partial parse aren't treated as valid fold targets.
|
||||||
|
|
||||||
|
Fix an issue where the parser sometimes wouldn't reuse parsing work done in the background on transactions.
|
||||||
|
|
||||||
|
## 0.19.8 (2022-03-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue that could cause indentation logic to use the wrong line content when indenting multiple lines at once.
|
||||||
|
|
||||||
|
## 0.19.7 (2021-12-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where the parse worker could incorrectly stop working when the parse tree has skipped gaps in it.
|
||||||
|
|
||||||
|
## 0.19.6 (2021-11-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fixes an issue where the background parse work would be scheduled too aggressively, degrading responsiveness on a newly-created editor with a large document.
|
||||||
|
|
||||||
|
Improve initial highlight for mixed-language editors and limit the amount of parsing done on state creation for faster startup.
|
||||||
|
|
||||||
|
## 0.19.5 (2021-11-17)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new function `syntaxTreeAvailable` can be used to check if a fully-parsed syntax tree is available up to a given document position.
|
||||||
|
|
||||||
|
The module now exports `syntaxParserRunning`, which tells you whether the background parser is still planning to do more work for a given editor view.
|
||||||
|
|
||||||
|
## 0.19.4 (2021-11-13)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`LanguageDescription.of` now takes an optional already-loaded extension.
|
||||||
|
|
||||||
|
## 0.19.3 (2021-09-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where a parse that skipped content with `skipUntilInView` would in some cases not be restarted when the range came into view.
|
||||||
|
|
||||||
|
## 0.19.2 (2021-08-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused `indentOnInput` to fire for the wrong kinds of transactions.
|
||||||
|
|
||||||
|
Fix a bug that could cause `indentOnInput` to apply its changes incorrectly.
|
||||||
|
|
||||||
|
## 0.19.1 (2021-08-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix incorrect versions for @lezer dependencies.
|
||||||
|
|
||||||
|
## 0.19.0 (2021-08-11)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
CodeMirror now uses lezer 0.15, which means different package names (scoped with @lezer) and some breaking changes in the library.
|
||||||
|
|
||||||
|
`EditorParseContext` is now called `ParseContext`. It is no longer passed to parsers, but must be retrieved with `ParseContext.get`.
|
||||||
|
|
||||||
|
`IndentContext.lineIndent` now takes a position, not a `Line` object, as argument.
|
||||||
|
|
||||||
|
`LezerLanguage` was renamed to `LRLanguage` (because all languages must emit Lezer-style trees, the name was misleading).
|
||||||
|
|
||||||
|
`Language.parseString` no longer exists. You can just call `.parser.parse(...)` instead.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
New `IndentContext.lineAt` method to access lines in a way that is aware of simulated line breaks.
|
||||||
|
|
||||||
|
`IndentContext` now provides a `simulatedBreak` property through which client code can query whether the context has a simulated line break.
|
||||||
|
|
||||||
|
## 0.18.2 (2021-06-01)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where asynchronous re-parsing (with dynamically loaded languages) sometimes failed to fully happen.
|
||||||
|
|
||||||
|
## 0.18.1 (2021-03-31)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
`EditorParseContext.getSkippingParser` now replaces `EditorParseContext.skippingParser` and allows you to provide a promise that'll cause parsing to start again. (The old property remains available until the next major release.)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where nested parsers could see past the end of the nested region.
|
||||||
|
|
||||||
|
## 0.18.0 (2021-03-03)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 0.18.
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
The `Language` constructor takes an additional argument that provides the top node type.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`Language` instances now have a `topNode` property giving their top node type.
|
||||||
|
|
||||||
|
`TreeIndentContext` now has a `continue` method that allows an indenter to defer to the indentation of the parent nodes.
|
||||||
|
|
||||||
|
## 0.17.5 (2021-02-19)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
This package now exports a `foldInside` helper function, a fold function that should work for most delimited node types.
|
||||||
|
|
||||||
|
## 0.17.4 (2021-01-15)
|
||||||
|
|
||||||
|
## 0.17.3 (2021-01-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Parse scheduling has been improved to reduce the likelyhood of the user looking at unparsed code in big documents.
|
||||||
|
|
||||||
|
Prevent parser from running too far past the current viewport in huge documents.
|
||||||
|
|
||||||
|
## 0.17.2 (2021-01-06)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now also exports a CommonJS module.
|
||||||
|
|
||||||
|
## 0.17.1 (2020-12-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where changing the editor configuration wouldn't update the language parser used.
|
||||||
|
|
||||||
|
## 0.17.0 (2020-12-29)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
First numbered release.
|
||||||
|
|
||||||
21
editor/node_modules/@codemirror/language/LICENSE
generated
vendored
Normal file
21
editor/node_modules/@codemirror/language/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
66
editor/node_modules/@codemirror/language/README.md
generated
vendored
Normal file
66
editor/node_modules/@codemirror/language/README.md
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# @codemirror/language [](https://www.npmjs.org/package/@codemirror/language)
|
||||||
|
|
||||||
|
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#language) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/) | [**CHANGELOG**](https://github.com/codemirror/language/blob/main/CHANGELOG.md) ]
|
||||||
|
|
||||||
|
This package implements the language support infrastructure for the
|
||||||
|
[CodeMirror](https://codemirror.net/) code editor.
|
||||||
|
|
||||||
|
The [project page](https://codemirror.net/) has more information, a
|
||||||
|
number of [examples](https://codemirror.net/examples/) and the
|
||||||
|
[documentation](https://codemirror.net/docs/).
|
||||||
|
|
||||||
|
This code is released under an
|
||||||
|
[MIT license](https://github.com/codemirror/language/tree/main/LICENSE).
|
||||||
|
|
||||||
|
We aim to be an inclusive, welcoming community. To make that explicit,
|
||||||
|
we have a [code of
|
||||||
|
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
||||||
|
to communication around the project.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Setting up a language from a [Lezer](https://lezer.codemirror.net)
|
||||||
|
parser looks like this:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {parser} from "@lezer/json"
|
||||||
|
import {LRLanguage, continuedIndent, indentNodeProp,
|
||||||
|
foldNodeProp, foldInside} from "@codemirror/language"
|
||||||
|
|
||||||
|
export const jsonLanguage = LRLanguage.define({
|
||||||
|
name: "json",
|
||||||
|
parser: parser.configure({
|
||||||
|
props: [
|
||||||
|
indentNodeProp.add({
|
||||||
|
Object: continuedIndent({except: /^\s*\}/}),
|
||||||
|
Array: continuedIndent({except: /^\s*\]/})
|
||||||
|
}),
|
||||||
|
foldNodeProp.add({
|
||||||
|
"Object Array": foldInside
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
languageData: {
|
||||||
|
closeBrackets: {brackets: ["[", "{", '"']},
|
||||||
|
indentOnInput: /^\s*[\}\]]$/
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Often, you'll also use this package just to access some specific
|
||||||
|
language-related features, such as accessing the editor's syntax
|
||||||
|
tree...
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {syntaxTree} from "@codemirror/language"
|
||||||
|
|
||||||
|
const tree = syntaxTree(view)
|
||||||
|
```
|
||||||
|
|
||||||
|
... or computing the appriate indentation at a given point.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {getIndentation} from "@codemirror/language"
|
||||||
|
|
||||||
|
console.log(getIndentation(view.state, view.state.selection.main.head))
|
||||||
|
```
|
||||||
2742
editor/node_modules/@codemirror/language/dist/index.cjs
generated
vendored
Normal file
2742
editor/node_modules/@codemirror/language/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1220
editor/node_modules/@codemirror/language/dist/index.d.cts
generated
vendored
Normal file
1220
editor/node_modules/@codemirror/language/dist/index.d.cts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1220
editor/node_modules/@codemirror/language/dist/index.d.ts
generated
vendored
Normal file
1220
editor/node_modules/@codemirror/language/dist/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2687
editor/node_modules/@codemirror/language/dist/index.js
generated
vendored
Normal file
2687
editor/node_modules/@codemirror/language/dist/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
44
editor/node_modules/@codemirror/language/package.json
generated
vendored
Normal file
44
editor/node_modules/@codemirror/language/package.json
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "@codemirror/language",
|
||||||
|
"version": "6.12.3",
|
||||||
|
"description": "Language support infrastructure for the CodeMirror code editor",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cm-runtests",
|
||||||
|
"prepare": "cm-buildhelper src/index.ts"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"code"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Marijn Haverbeke",
|
||||||
|
"email": "marijn@haverbeke.berlin",
|
||||||
|
"url": "http://marijnhaverbeke.nl"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"sideEffects": false,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.23.0",
|
||||||
|
"@lezer/common": "^1.5.0",
|
||||||
|
"@lezer/highlight": "^1.0.0",
|
||||||
|
"@lezer/lr": "^1.0.0",
|
||||||
|
"style-mod": "^4.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/buildhelper": "^1.0.0",
|
||||||
|
"@lezer/javascript": "^1.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/codemirror/language.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
16
editor/node_modules/@codemirror/lint/.github/workflows/dispatch.yml
generated
vendored
Normal file
16
editor/node_modules/@codemirror/lint/.github/workflows/dispatch.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Trigger CI
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Dispatch to main repo
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Emit repository_dispatch
|
||||||
|
uses: mvasigh/dispatch-action@main
|
||||||
|
with:
|
||||||
|
# You should create a personal access token and store it in your repository
|
||||||
|
token: ${{ secrets.DISPATCH_AUTH }}
|
||||||
|
repo: dev
|
||||||
|
owner: codemirror
|
||||||
|
event_type: push
|
||||||
318
editor/node_modules/@codemirror/lint/CHANGELOG.md
generated
vendored
Normal file
318
editor/node_modules/@codemirror/lint/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
## 6.9.5 (2026-03-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Use more appropriate background colors for the selected diagnostic in dark mode.
|
||||||
|
|
||||||
|
## 6.9.4 (2026-02-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure `nextDiagnostic` selects entire diagnostics, even when they overlap with other diagnostics.
|
||||||
|
|
||||||
|
## 6.9.3 (2026-01-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where the lint panel inappropriately blocks the default behavior of key combinations with Ctrl, Alt, or Cmd held.
|
||||||
|
|
||||||
|
## 6.9.2 (2025-11-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an infinite loop that would occur when a diagnostic pointed beyond the end of the document.
|
||||||
|
|
||||||
|
## 6.9.1 (2025-10-23)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Properly display diagnostics that just cover multiple newlines as widgets.
|
||||||
|
|
||||||
|
## 6.9.0 (2025-10-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Multiple configurations to `linter` will now be merged without raising an error.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `markClass` option to actions makes it possible to style action buttons.
|
||||||
|
|
||||||
|
## 6.8.5 (2025-03-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a regression (since 6.8.4) that broke the `markerFilter` option.
|
||||||
|
|
||||||
|
## 6.8.4 (2024-11-28)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't create overlapping decorations when diagnostics overlap.
|
||||||
|
|
||||||
|
Fix an issue where block widgets could cause the lint gutter to show diagnostics multiple times.
|
||||||
|
|
||||||
|
## 6.8.3 (2024-11-21)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue that prevented tooltips in the lint gutter from being displayed.
|
||||||
|
|
||||||
|
## 6.8.2 (2024-09-24)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Show lint markers for code replaced by a block widget.
|
||||||
|
|
||||||
|
When multiple linters are installed, start displaying results from ones that return quickly even if others are slow to return.
|
||||||
|
|
||||||
|
## 6.8.1 (2024-06-19)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make lint markers non-inclusive again, since having them that way causes more issues than it solves.
|
||||||
|
|
||||||
|
## 6.8.0 (2024-05-23)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `autoPanel` option can be used to make the panel automatically appear when diagnostics are added and close when no diagnostics are left.
|
||||||
|
|
||||||
|
## 6.7.1 (2024-05-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't perform an additional superfluous timed lint run after `forceLinting` has been called.
|
||||||
|
|
||||||
|
## 6.7.0 (2024-04-30)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `renderMessage` function is now called with the editor view as first argument.
|
||||||
|
|
||||||
|
## 6.6.0 (2024-04-29)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `hideOn` configuration option can be used to control in what circumstances lint tooltips get hidden by state changes.
|
||||||
|
|
||||||
|
## 6.5.0 (2024-01-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make lint mark decorations inclusive, so that they are applied even if the marked content is replaced by a widget decoration.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`linter` can now be called with null as source to only provide a configuration.
|
||||||
|
|
||||||
|
`markerFilter` and `tooltipFilter` function now get passed the current editor state.
|
||||||
|
|
||||||
|
## 6.4.2 (2023-09-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure scrolling diagnostic into view in the panel works when the editor is scaled.
|
||||||
|
|
||||||
|
## 6.4.1 (2023-08-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a crash that could occur when a view was reconfigured in a way that removed the lint extension.
|
||||||
|
|
||||||
|
## 6.4.0 (2023-07-03)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Diagnostics can now use `"hint"` as a severity level.
|
||||||
|
|
||||||
|
Diagnostics can now set a `markClass` property to add an additional CSS class to the text marked by the diagnostic.
|
||||||
|
|
||||||
|
## 6.3.0 (2023-06-23)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
A new `previousDiagnostic` command can be used to move back through the active diagnostics.
|
||||||
|
|
||||||
|
## 6.2.2 (2023-06-05)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure lint gutter tooltips are properly closed when the content of their line changes.
|
||||||
|
|
||||||
|
## 6.2.1 (2023-04-13)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
The `linter` function now eagerly includes all lint-related extensions, rather than appending them to the configuration as-needed, so that turning off linting by clearing the compartment that contains it works properly.
|
||||||
|
|
||||||
|
## 6.2.0 (2023-02-27)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `needsRefresh` option to `linter` makes it possible to cause linting to be recalculated for non-document state changes.
|
||||||
|
|
||||||
|
## 6.1.1 (2023-02-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Give lint action buttons a pointer cursor style.
|
||||||
|
|
||||||
|
Fix a bug that caused diagnostic action callbacks to be called twice when their button was clicked.
|
||||||
|
|
||||||
|
## 6.1.0 (2022-11-15)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `forEachDiagnostic` function can be used to iterate over the diagnostics in an editor state.
|
||||||
|
|
||||||
|
## 6.0.0 (2022-06-08)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 6.0.0
|
||||||
|
|
||||||
|
## 0.20.3 (2022-05-25)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Diagnostic objects may now have a `renderMessage` method to render their message to the DOM.
|
||||||
|
|
||||||
|
## 0.20.2 (2022-05-02)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now exports the `LintSource` function type.
|
||||||
|
|
||||||
|
The new `markerFilter` and `tooltipFilter` options to `linter` and `lintGutter` allow more control over which diagnostics are visible and which have tooltips.
|
||||||
|
|
||||||
|
## 0.20.1 (2022-04-22)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Hide lint tooltips when the document is changed.
|
||||||
|
|
||||||
|
## 0.20.0 (2022-04-20)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 0.20.0
|
||||||
|
|
||||||
|
## 0.19.6 (2022-03-04)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where hovering over the icons in the lint gutter would sometimes fail to show a tooltip or show the tooltip for another line.
|
||||||
|
|
||||||
|
## 0.19.5 (2022-02-25)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure the lint gutter tooltips are positioned under their icon, even when the line is wrapped.
|
||||||
|
|
||||||
|
## 0.19.4 (2022-02-25)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where an outdated marker could stick around on the lint gutter after all diagnostics were removed.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Add a `hoverTime` option to the lint gutter. Change default hover time to 300
|
||||||
|
|
||||||
|
## 0.19.3 (2021-11-09)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Export a function `lintGutter` which returns an extension that installs a gutter marking lines with diagnostics.
|
||||||
|
|
||||||
|
The package now exports the effect used to update the diagnostics (`setDiagnosticsEffect`).
|
||||||
|
|
||||||
|
## 0.19.2 (2021-09-29)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where reconfiguring the lint source didn't restart linting.
|
||||||
|
|
||||||
|
## 0.19.1 (2021-09-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Prevent decorations that cover just a line break from being invisible by showing a widget instead of range for them.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `diagnosticCount` method can now be used to determine whether there are active diagnostics.
|
||||||
|
|
||||||
|
## 0.19.0 (2021-08-11)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 0.19.0
|
||||||
|
|
||||||
|
## 0.18.6 (2021-08-08)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a crash in the key handler of the lint panel when no diagnostics are available.
|
||||||
|
|
||||||
|
## 0.18.5 (2021-08-07)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue that caused `openLintPanel` to not actually open the panel when ran before the editor had any lint state loaded.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now exports a `forceLinting` function that forces pending lint queries to run immediately.
|
||||||
|
|
||||||
|
## 0.18.4 (2021-06-07)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Multiple `linter` extensions can now be added to an editor without disrupting each other.
|
||||||
|
|
||||||
|
Fix poor layout on lint tooltips due to changes in @codemirror/tooltip.
|
||||||
|
|
||||||
|
## 0.18.3 (2021-05-10)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a regression where using `setDiagnostics` when linting hadn't been abled yet ignored the first set of diagnostics.
|
||||||
|
|
||||||
|
## 0.18.2 (2021-04-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Newlines in line messages are now shown as line breaks to the user.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
You can now pass a delay option to `linter` to configure how long it waits before calling the linter.
|
||||||
|
|
||||||
|
## 0.18.1 (2021-03-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Adjust to current @codemirror/panel and @codemirror/tooltip interfaces.
|
||||||
|
|
||||||
|
## 0.18.0 (2021-03-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure action access keys are discoverable for screen reader users.
|
||||||
|
|
||||||
|
Selection in the lint panel should now be properly visible to screen readers.
|
||||||
|
|
||||||
|
## 0.17.1 (2021-01-06)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now also exports a CommonJS module.
|
||||||
|
|
||||||
|
## 0.17.0 (2020-12-29)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
First numbered release.
|
||||||
|
|
||||||
21
editor/node_modules/@codemirror/lint/LICENSE
generated
vendored
Normal file
21
editor/node_modules/@codemirror/lint/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
18
editor/node_modules/@codemirror/lint/README.md
generated
vendored
Normal file
18
editor/node_modules/@codemirror/lint/README.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# @codemirror/lint [](https://www.npmjs.org/package/@codemirror/lint)
|
||||||
|
|
||||||
|
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#lint) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lint/blob/main/CHANGELOG.md) ]
|
||||||
|
|
||||||
|
This package implements linting support for the
|
||||||
|
[CodeMirror](https://codemirror.net/) code editor.
|
||||||
|
|
||||||
|
The [project page](https://codemirror.net/) has more information, a
|
||||||
|
number of [examples](https://codemirror.net/examples/) and the
|
||||||
|
[documentation](https://codemirror.net/docs/).
|
||||||
|
|
||||||
|
This code is released under an
|
||||||
|
[MIT license](https://github.com/codemirror/lint/tree/main/LICENSE).
|
||||||
|
|
||||||
|
We aim to be an inclusive, welcoming community. To make that explicit,
|
||||||
|
we have a [code of
|
||||||
|
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
||||||
|
to communication around the project.
|
||||||
958
editor/node_modules/@codemirror/lint/dist/index.cjs
generated
vendored
Normal file
958
editor/node_modules/@codemirror/lint/dist/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,958 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var view = require('@codemirror/view');
|
||||||
|
var state = require('@codemirror/state');
|
||||||
|
var elt = require('crelt');
|
||||||
|
|
||||||
|
class SelectedDiagnostic {
|
||||||
|
constructor(from, to, diagnostic) {
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.diagnostic = diagnostic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class LintState {
|
||||||
|
constructor(diagnostics, panel, selected) {
|
||||||
|
this.diagnostics = diagnostics;
|
||||||
|
this.panel = panel;
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
static init(diagnostics, panel, state$1) {
|
||||||
|
// Filter the list of diagnostics for which to create markers
|
||||||
|
let diagnosticFilter = state$1.facet(lintConfig).markerFilter;
|
||||||
|
if (diagnosticFilter)
|
||||||
|
diagnostics = diagnosticFilter(diagnostics, state$1);
|
||||||
|
let sorted = diagnostics.slice().sort((a, b) => a.from - b.from || a.to - b.to);
|
||||||
|
let deco = new state.RangeSetBuilder(), active = [], pos = 0;
|
||||||
|
let scan = state$1.doc.iter(), scanPos = 0, docLen = state$1.doc.length;
|
||||||
|
for (let i = 0;;) {
|
||||||
|
let next = i == sorted.length ? null : sorted[i];
|
||||||
|
if (!next && !active.length)
|
||||||
|
break;
|
||||||
|
let from, to;
|
||||||
|
if (active.length) {
|
||||||
|
from = pos;
|
||||||
|
to = active.reduce((p, d) => Math.min(p, d.to), next && next.from > from ? next.from : 1e8);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
from = next.from;
|
||||||
|
if (from > docLen)
|
||||||
|
break;
|
||||||
|
to = next.to;
|
||||||
|
active.push(next);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (i < sorted.length) {
|
||||||
|
let next = sorted[i];
|
||||||
|
if (next.from == from && (next.to > next.from || next.to == from)) {
|
||||||
|
active.push(next);
|
||||||
|
i++;
|
||||||
|
to = Math.min(next.to, to);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
to = Math.min(next.from, to);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to = Math.min(to, docLen);
|
||||||
|
let widget = false;
|
||||||
|
if (active.some(d => d.from == from && (d.to == to || to == docLen))) {
|
||||||
|
widget = from == to;
|
||||||
|
if (!widget && to - from < 10) {
|
||||||
|
let behind = from - (scanPos + scan.value.length);
|
||||||
|
if (behind > 0) {
|
||||||
|
scan.next(behind);
|
||||||
|
scanPos = from;
|
||||||
|
}
|
||||||
|
for (let check = from;;) {
|
||||||
|
if (check >= to) {
|
||||||
|
widget = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!scan.lineBreak && scanPos + scan.value.length > check)
|
||||||
|
break;
|
||||||
|
check = scanPos + scan.value.length;
|
||||||
|
scanPos += scan.value.length;
|
||||||
|
scan.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let sev = maxSeverity(active);
|
||||||
|
if (widget) {
|
||||||
|
deco.add(from, from, view.Decoration.widget({
|
||||||
|
widget: new DiagnosticWidget(sev),
|
||||||
|
diagnostics: active.slice()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let markClass = active.reduce((c, d) => d.markClass ? c + " " + d.markClass : c, "");
|
||||||
|
deco.add(from, to, view.Decoration.mark({
|
||||||
|
class: "cm-lintRange cm-lintRange-" + sev + markClass,
|
||||||
|
diagnostics: active.slice(),
|
||||||
|
inclusiveEnd: active.some(a => a.to > to)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
pos = to;
|
||||||
|
if (pos == docLen)
|
||||||
|
break;
|
||||||
|
for (let i = 0; i < active.length; i++)
|
||||||
|
if (active[i].to <= pos)
|
||||||
|
active.splice(i--, 1);
|
||||||
|
}
|
||||||
|
let set = deco.finish();
|
||||||
|
return new LintState(set, panel, findDiagnostic(set));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
|
||||||
|
let found = null;
|
||||||
|
diagnostics.between(after, 1e9, (from, to, { spec }) => {
|
||||||
|
if (diagnostic && spec.diagnostics.indexOf(diagnostic) < 0)
|
||||||
|
return;
|
||||||
|
if (!found)
|
||||||
|
found = new SelectedDiagnostic(from, to, diagnostic || spec.diagnostics[0]);
|
||||||
|
else if (spec.diagnostics.indexOf(found.diagnostic) < 0)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
found = new SelectedDiagnostic(found.from, to, found.diagnostic);
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
function hideTooltip(tr, tooltip) {
|
||||||
|
let from = tooltip.pos, to = tooltip.end || from;
|
||||||
|
let result = tr.state.facet(lintConfig).hideOn(tr, from, to);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
let line = tr.startState.doc.lineAt(tooltip.pos);
|
||||||
|
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, Math.max(line.to, to)));
|
||||||
|
}
|
||||||
|
function maybeEnableLint(state$1, effects) {
|
||||||
|
return state$1.field(lintState, false) ? effects : effects.concat(state.StateEffect.appendConfig.of(lintExtensions));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Returns a transaction spec which updates the current set of
|
||||||
|
diagnostics, and enables the lint extension if if wasn't already
|
||||||
|
active.
|
||||||
|
*/
|
||||||
|
function setDiagnostics(state, diagnostics) {
|
||||||
|
return {
|
||||||
|
effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
The state effect that updates the set of active diagnostics. Can
|
||||||
|
be useful when writing an extension that needs to track these.
|
||||||
|
*/
|
||||||
|
const setDiagnosticsEffect = state.StateEffect.define();
|
||||||
|
const togglePanel = state.StateEffect.define();
|
||||||
|
const movePanelSelection = state.StateEffect.define();
|
||||||
|
const lintState = state.StateField.define({
|
||||||
|
create() {
|
||||||
|
return new LintState(view.Decoration.none, null, null);
|
||||||
|
},
|
||||||
|
update(value, tr) {
|
||||||
|
if (tr.docChanged && value.diagnostics.size) {
|
||||||
|
let mapped = value.diagnostics.map(tr.changes), selected = null, panel = value.panel;
|
||||||
|
if (value.selected) {
|
||||||
|
let selPos = tr.changes.mapPos(value.selected.from, 1);
|
||||||
|
selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos);
|
||||||
|
}
|
||||||
|
if (!mapped.size && panel && tr.state.facet(lintConfig).autoPanel)
|
||||||
|
panel = null;
|
||||||
|
value = new LintState(mapped, panel, selected);
|
||||||
|
}
|
||||||
|
for (let effect of tr.effects) {
|
||||||
|
if (effect.is(setDiagnosticsEffect)) {
|
||||||
|
let panel = !tr.state.facet(lintConfig).autoPanel ? value.panel : effect.value.length ? LintPanel.open : null;
|
||||||
|
value = LintState.init(effect.value, panel, tr.state);
|
||||||
|
}
|
||||||
|
else if (effect.is(togglePanel)) {
|
||||||
|
value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected);
|
||||||
|
}
|
||||||
|
else if (effect.is(movePanelSelection)) {
|
||||||
|
value = new LintState(value.diagnostics, value.panel, effect.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
provide: f => [view.showPanel.from(f, val => val.panel),
|
||||||
|
view.EditorView.decorations.from(f, s => s.diagnostics)]
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
Returns the number of active lint diagnostics in the given state.
|
||||||
|
*/
|
||||||
|
function diagnosticCount(state) {
|
||||||
|
let lint = state.field(lintState, false);
|
||||||
|
return lint ? lint.diagnostics.size : 0;
|
||||||
|
}
|
||||||
|
const activeMark = view.Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
|
||||||
|
function lintTooltip(view, pos, side) {
|
||||||
|
let { diagnostics } = view.state.field(lintState);
|
||||||
|
let found, start = -1, end = -1;
|
||||||
|
diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => {
|
||||||
|
if (pos >= from && pos <= to &&
|
||||||
|
(from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) {
|
||||||
|
found = spec.diagnostics;
|
||||||
|
start = from;
|
||||||
|
end = to;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
||||||
|
if (found && diagnosticFilter)
|
||||||
|
found = diagnosticFilter(found, view.state);
|
||||||
|
if (!found)
|
||||||
|
return null;
|
||||||
|
return {
|
||||||
|
pos: start,
|
||||||
|
end: end,
|
||||||
|
above: view.state.doc.lineAt(start).to < end,
|
||||||
|
create() {
|
||||||
|
return { dom: diagnosticsTooltip(view, found) };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function diagnosticsTooltip(view, diagnostics) {
|
||||||
|
return elt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false)));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Command to open and focus the lint panel.
|
||||||
|
*/
|
||||||
|
const openLintPanel = (view$1) => {
|
||||||
|
let field = view$1.state.field(lintState, false);
|
||||||
|
if (!field || !field.panel)
|
||||||
|
view$1.dispatch({ effects: maybeEnableLint(view$1.state, [togglePanel.of(true)]) });
|
||||||
|
let panel = view.getPanel(view$1, LintPanel.open);
|
||||||
|
if (panel)
|
||||||
|
panel.dom.querySelector(".cm-panel-lint ul").focus();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Command to close the lint panel, when open.
|
||||||
|
*/
|
||||||
|
const closeLintPanel = (view) => {
|
||||||
|
let field = view.state.field(lintState, false);
|
||||||
|
if (!field || !field.panel)
|
||||||
|
return false;
|
||||||
|
view.dispatch({ effects: togglePanel.of(false) });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Move the selection to the next diagnostic.
|
||||||
|
*/
|
||||||
|
const nextDiagnostic = (view) => {
|
||||||
|
let field = view.state.field(lintState, false);
|
||||||
|
if (!field)
|
||||||
|
return false;
|
||||||
|
let sel = view.state.selection.main, next = findDiagnostic(field.diagnostics, null, sel.to + 1);
|
||||||
|
if (!next) {
|
||||||
|
next = findDiagnostic(field.diagnostics, null, 0);
|
||||||
|
if (!next || next.from == sel.from && next.to == sel.to)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
view.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Move the selection to the previous diagnostic.
|
||||||
|
*/
|
||||||
|
const previousDiagnostic = (view) => {
|
||||||
|
let { state } = view, field = state.field(lintState, false);
|
||||||
|
if (!field)
|
||||||
|
return false;
|
||||||
|
let sel = state.selection.main;
|
||||||
|
let prevFrom, prevTo, lastFrom, lastTo;
|
||||||
|
field.diagnostics.between(0, state.doc.length, (from, to) => {
|
||||||
|
if (to < sel.to && (prevFrom == null || prevFrom < from)) {
|
||||||
|
prevFrom = from;
|
||||||
|
prevTo = to;
|
||||||
|
}
|
||||||
|
if (lastFrom == null || from > lastFrom) {
|
||||||
|
lastFrom = from;
|
||||||
|
lastTo = to;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (lastFrom == null || prevFrom == null && lastFrom == sel.from)
|
||||||
|
return false;
|
||||||
|
view.dispatch({ selection: { anchor: prevFrom !== null && prevFrom !== void 0 ? prevFrom : lastFrom, head: prevTo !== null && prevTo !== void 0 ? prevTo : lastTo }, scrollIntoView: true });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
A set of default key bindings for the lint functionality.
|
||||||
|
|
||||||
|
- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
|
||||||
|
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
||||||
|
*/
|
||||||
|
const lintKeymap = [
|
||||||
|
{ key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
|
||||||
|
{ key: "F8", run: nextDiagnostic }
|
||||||
|
];
|
||||||
|
const lintPlugin = view.ViewPlugin.fromClass(class {
|
||||||
|
constructor(view) {
|
||||||
|
this.view = view;
|
||||||
|
this.timeout = -1;
|
||||||
|
this.set = true;
|
||||||
|
let { delay } = view.state.facet(lintConfig);
|
||||||
|
this.lintTime = Date.now() + delay;
|
||||||
|
this.run = this.run.bind(this);
|
||||||
|
this.timeout = setTimeout(this.run, delay);
|
||||||
|
}
|
||||||
|
run() {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
let now = Date.now();
|
||||||
|
if (now < this.lintTime - 10) {
|
||||||
|
this.timeout = setTimeout(this.run, this.lintTime - now);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.set = false;
|
||||||
|
let { state } = this.view, { sources } = state.facet(lintConfig);
|
||||||
|
if (sources.length)
|
||||||
|
batchResults(sources.map(s => Promise.resolve(s(this.view))), annotations => {
|
||||||
|
if (this.view.state.doc == state.doc)
|
||||||
|
this.view.dispatch(setDiagnostics(this.view.state, annotations.reduce((a, b) => a.concat(b))));
|
||||||
|
}, error => { view.logException(this.view.state, error); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update(update) {
|
||||||
|
let config = update.state.facet(lintConfig);
|
||||||
|
if (update.docChanged || config != update.startState.facet(lintConfig) ||
|
||||||
|
config.needsRefresh && config.needsRefresh(update)) {
|
||||||
|
this.lintTime = Date.now() + config.delay;
|
||||||
|
if (!this.set) {
|
||||||
|
this.set = true;
|
||||||
|
this.timeout = setTimeout(this.run, config.delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
force() {
|
||||||
|
if (this.set) {
|
||||||
|
this.lintTime = Date.now();
|
||||||
|
this.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function batchResults(promises, sink, error) {
|
||||||
|
let collected = [], timeout = -1;
|
||||||
|
for (let p of promises)
|
||||||
|
p.then(value => {
|
||||||
|
collected.push(value);
|
||||||
|
clearTimeout(timeout);
|
||||||
|
if (collected.length == promises.length)
|
||||||
|
sink(collected);
|
||||||
|
else
|
||||||
|
timeout = setTimeout(() => sink(collected), 200);
|
||||||
|
}, error);
|
||||||
|
}
|
||||||
|
const lintConfig = state.Facet.define({
|
||||||
|
combine(input) {
|
||||||
|
return {
|
||||||
|
sources: input.map(i => i.source).filter(x => x != null),
|
||||||
|
...state.combineConfig(input.map(i => i.config), {
|
||||||
|
delay: 750,
|
||||||
|
markerFilter: null,
|
||||||
|
tooltipFilter: null,
|
||||||
|
needsRefresh: null,
|
||||||
|
hideOn: () => null,
|
||||||
|
}, {
|
||||||
|
delay: Math.max,
|
||||||
|
markerFilter: combineFilter,
|
||||||
|
tooltipFilter: combineFilter,
|
||||||
|
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u),
|
||||||
|
hideOn: (a, b) => !a ? b : !b ? a : (t, x, y) => a(t, x, y) || b(t, x, y),
|
||||||
|
autoPanel: (a, b) => a || b
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function combineFilter(a, b) {
|
||||||
|
return !a ? b : !b ? a : (d, s) => b(a(d, s), s);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Given a diagnostic source, this function returns an extension that
|
||||||
|
enables linting with that source. It will be called whenever the
|
||||||
|
editor is idle (after its content changed).
|
||||||
|
|
||||||
|
Note that settings given here will apply to all linters active in
|
||||||
|
the editor. If `null` is given as source, this only configures the
|
||||||
|
lint extension.
|
||||||
|
*/
|
||||||
|
function linter(source, config = {}) {
|
||||||
|
return [
|
||||||
|
lintConfig.of({ source, config }),
|
||||||
|
lintPlugin,
|
||||||
|
lintExtensions
|
||||||
|
];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
||||||
|
editor is idle to run right away.
|
||||||
|
*/
|
||||||
|
function forceLinting(view) {
|
||||||
|
let plugin = view.plugin(lintPlugin);
|
||||||
|
if (plugin)
|
||||||
|
plugin.force();
|
||||||
|
}
|
||||||
|
function assignKeys(actions) {
|
||||||
|
let assigned = [];
|
||||||
|
if (actions)
|
||||||
|
actions: for (let { name } of actions) {
|
||||||
|
for (let i = 0; i < name.length; i++) {
|
||||||
|
let ch = name[i];
|
||||||
|
if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) {
|
||||||
|
assigned.push(ch);
|
||||||
|
continue actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assigned.push("");
|
||||||
|
}
|
||||||
|
return assigned;
|
||||||
|
}
|
||||||
|
function renderDiagnostic(view, diagnostic, inPanel) {
|
||||||
|
var _a;
|
||||||
|
let keys = inPanel ? assignKeys(diagnostic.actions) : [];
|
||||||
|
return elt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, elt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage(view) : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {
|
||||||
|
let fired = false, click = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (fired)
|
||||||
|
return;
|
||||||
|
fired = true;
|
||||||
|
let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
|
||||||
|
if (found)
|
||||||
|
action.apply(view, found.from, found.to);
|
||||||
|
};
|
||||||
|
let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1;
|
||||||
|
let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
|
||||||
|
elt("u", name.slice(keyIndex, keyIndex + 1)),
|
||||||
|
name.slice(keyIndex + 1)];
|
||||||
|
let markClass = action.markClass ? " " + action.markClass : "";
|
||||||
|
return elt("button", {
|
||||||
|
type: "button",
|
||||||
|
class: "cm-diagnosticAction" + markClass,
|
||||||
|
onclick: click,
|
||||||
|
onmousedown: click,
|
||||||
|
"aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
|
||||||
|
}, nameElt);
|
||||||
|
}), diagnostic.source && elt("div", { class: "cm-diagnosticSource" }, diagnostic.source));
|
||||||
|
}
|
||||||
|
class DiagnosticWidget extends view.WidgetType {
|
||||||
|
constructor(sev) {
|
||||||
|
super();
|
||||||
|
this.sev = sev;
|
||||||
|
}
|
||||||
|
eq(other) { return other.sev == this.sev; }
|
||||||
|
toDOM() {
|
||||||
|
return elt("span", { class: "cm-lintPoint cm-lintPoint-" + this.sev });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class PanelItem {
|
||||||
|
constructor(view, diagnostic) {
|
||||||
|
this.diagnostic = diagnostic;
|
||||||
|
this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16);
|
||||||
|
this.dom = renderDiagnostic(view, diagnostic, true);
|
||||||
|
this.dom.id = this.id;
|
||||||
|
this.dom.setAttribute("role", "option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class LintPanel {
|
||||||
|
constructor(view) {
|
||||||
|
this.view = view;
|
||||||
|
this.items = [];
|
||||||
|
let onkeydown = (event) => {
|
||||||
|
if (event.ctrlKey || event.altKey || event.metaKey)
|
||||||
|
return;
|
||||||
|
if (event.keyCode == 27) { // Escape
|
||||||
|
closeLintPanel(this.view);
|
||||||
|
this.view.focus();
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp
|
||||||
|
this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown
|
||||||
|
this.moveSelection((this.selectedIndex + 1) % this.items.length);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 36) { // Home
|
||||||
|
this.moveSelection(0);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 35) { // End
|
||||||
|
this.moveSelection(this.items.length - 1);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 13) { // Enter
|
||||||
|
this.view.focus();
|
||||||
|
}
|
||||||
|
else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z
|
||||||
|
let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions);
|
||||||
|
for (let i = 0; i < keys.length; i++)
|
||||||
|
if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) {
|
||||||
|
let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic);
|
||||||
|
if (found)
|
||||||
|
diagnostic.actions[i].apply(view, found.from, found.to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
};
|
||||||
|
let onclick = (event) => {
|
||||||
|
for (let i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].dom.contains(event.target))
|
||||||
|
this.moveSelection(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.list = elt("ul", {
|
||||||
|
tabIndex: 0,
|
||||||
|
role: "listbox",
|
||||||
|
"aria-label": this.view.state.phrase("Diagnostics"),
|
||||||
|
onkeydown,
|
||||||
|
onclick
|
||||||
|
});
|
||||||
|
this.dom = elt("div", { class: "cm-panel-lint" }, this.list, elt("button", {
|
||||||
|
type: "button",
|
||||||
|
name: "close",
|
||||||
|
"aria-label": this.view.state.phrase("close"),
|
||||||
|
onclick: () => closeLintPanel(this.view)
|
||||||
|
}, "×"));
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
get selectedIndex() {
|
||||||
|
let selected = this.view.state.field(lintState).selected;
|
||||||
|
if (!selected)
|
||||||
|
return -1;
|
||||||
|
for (let i = 0; i < this.items.length; i++)
|
||||||
|
if (this.items[i].diagnostic == selected.diagnostic)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
update() {
|
||||||
|
let { diagnostics, selected } = this.view.state.field(lintState);
|
||||||
|
let i = 0, needsSync = false, newSelectedItem = null;
|
||||||
|
let seen = new Set();
|
||||||
|
diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => {
|
||||||
|
for (let diagnostic of spec.diagnostics) {
|
||||||
|
if (seen.has(diagnostic))
|
||||||
|
continue;
|
||||||
|
seen.add(diagnostic);
|
||||||
|
let found = -1, item;
|
||||||
|
for (let j = i; j < this.items.length; j++)
|
||||||
|
if (this.items[j].diagnostic == diagnostic) {
|
||||||
|
found = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (found < 0) {
|
||||||
|
item = new PanelItem(this.view, diagnostic);
|
||||||
|
this.items.splice(i, 0, item);
|
||||||
|
needsSync = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
item = this.items[found];
|
||||||
|
if (found > i) {
|
||||||
|
this.items.splice(i, found - i);
|
||||||
|
needsSync = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selected && item.diagnostic == selected.diagnostic) {
|
||||||
|
if (!item.dom.hasAttribute("aria-selected")) {
|
||||||
|
item.dom.setAttribute("aria-selected", "true");
|
||||||
|
newSelectedItem = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (item.dom.hasAttribute("aria-selected")) {
|
||||||
|
item.dom.removeAttribute("aria-selected");
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) {
|
||||||
|
needsSync = true;
|
||||||
|
this.items.pop();
|
||||||
|
}
|
||||||
|
if (this.items.length == 0) {
|
||||||
|
this.items.push(new PanelItem(this.view, {
|
||||||
|
from: -1, to: -1,
|
||||||
|
severity: "info",
|
||||||
|
message: this.view.state.phrase("No diagnostics")
|
||||||
|
}));
|
||||||
|
needsSync = true;
|
||||||
|
}
|
||||||
|
if (newSelectedItem) {
|
||||||
|
this.list.setAttribute("aria-activedescendant", newSelectedItem.id);
|
||||||
|
this.view.requestMeasure({
|
||||||
|
key: this,
|
||||||
|
read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }),
|
||||||
|
write: ({ sel, panel }) => {
|
||||||
|
let scaleY = panel.height / this.list.offsetHeight;
|
||||||
|
if (sel.top < panel.top)
|
||||||
|
this.list.scrollTop -= (panel.top - sel.top) / scaleY;
|
||||||
|
else if (sel.bottom > panel.bottom)
|
||||||
|
this.list.scrollTop += (sel.bottom - panel.bottom) / scaleY;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (this.selectedIndex < 0) {
|
||||||
|
this.list.removeAttribute("aria-activedescendant");
|
||||||
|
}
|
||||||
|
if (needsSync)
|
||||||
|
this.sync();
|
||||||
|
}
|
||||||
|
sync() {
|
||||||
|
let domPos = this.list.firstChild;
|
||||||
|
function rm() {
|
||||||
|
let prev = domPos;
|
||||||
|
domPos = prev.nextSibling;
|
||||||
|
prev.remove();
|
||||||
|
}
|
||||||
|
for (let item of this.items) {
|
||||||
|
if (item.dom.parentNode == this.list) {
|
||||||
|
while (domPos != item.dom)
|
||||||
|
rm();
|
||||||
|
domPos = item.dom.nextSibling;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.list.insertBefore(item.dom, domPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (domPos)
|
||||||
|
rm();
|
||||||
|
}
|
||||||
|
moveSelection(selectedIndex) {
|
||||||
|
if (this.selectedIndex < 0)
|
||||||
|
return;
|
||||||
|
let field = this.view.state.field(lintState);
|
||||||
|
let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic);
|
||||||
|
if (!selection)
|
||||||
|
return;
|
||||||
|
this.view.dispatch({
|
||||||
|
selection: { anchor: selection.from, head: selection.to },
|
||||||
|
scrollIntoView: true,
|
||||||
|
effects: movePanelSelection.of(selection)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
static open(view) { return new LintPanel(view); }
|
||||||
|
}
|
||||||
|
function svg(content, attrs = `viewBox="0 0 40 40"`) {
|
||||||
|
return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
|
||||||
|
}
|
||||||
|
function underline(color) {
|
||||||
|
return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, `width="6" height="3"`);
|
||||||
|
}
|
||||||
|
const baseTheme = view.EditorView.baseTheme({
|
||||||
|
".cm-diagnostic": {
|
||||||
|
padding: "3px 6px 3px 8px",
|
||||||
|
marginLeft: "-1px",
|
||||||
|
display: "block",
|
||||||
|
whiteSpace: "pre-wrap"
|
||||||
|
},
|
||||||
|
".cm-diagnostic-error": { borderLeft: "5px solid #d11" },
|
||||||
|
".cm-diagnostic-warning": { borderLeft: "5px solid orange" },
|
||||||
|
".cm-diagnostic-info": { borderLeft: "5px solid #999" },
|
||||||
|
".cm-diagnostic-hint": { borderLeft: "5px solid #66d" },
|
||||||
|
".cm-diagnosticAction": {
|
||||||
|
font: "inherit",
|
||||||
|
border: "none",
|
||||||
|
padding: "2px 4px",
|
||||||
|
backgroundColor: "#444",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "3px",
|
||||||
|
marginLeft: "8px",
|
||||||
|
cursor: "pointer"
|
||||||
|
},
|
||||||
|
".cm-diagnosticSource": {
|
||||||
|
fontSize: "70%",
|
||||||
|
opacity: .7
|
||||||
|
},
|
||||||
|
".cm-lintRange": {
|
||||||
|
backgroundPosition: "left bottom",
|
||||||
|
backgroundRepeat: "repeat-x",
|
||||||
|
paddingBottom: "0.7px",
|
||||||
|
},
|
||||||
|
".cm-lintRange-error": { backgroundImage: underline("#d11") },
|
||||||
|
".cm-lintRange-warning": { backgroundImage: underline("orange") },
|
||||||
|
".cm-lintRange-info": { backgroundImage: underline("#999") },
|
||||||
|
".cm-lintRange-hint": { backgroundImage: underline("#66d") },
|
||||||
|
".cm-lintRange-active": { backgroundColor: "#ffdd9980" },
|
||||||
|
".cm-tooltip-lint": {
|
||||||
|
padding: 0,
|
||||||
|
margin: 0
|
||||||
|
},
|
||||||
|
".cm-lintPoint": {
|
||||||
|
position: "relative",
|
||||||
|
"&:after": {
|
||||||
|
content: '""',
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 0,
|
||||||
|
left: "-2px",
|
||||||
|
borderLeft: "3px solid transparent",
|
||||||
|
borderRight: "3px solid transparent",
|
||||||
|
borderBottom: "4px solid #d11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".cm-lintPoint-warning": {
|
||||||
|
"&:after": { borderBottomColor: "orange" }
|
||||||
|
},
|
||||||
|
".cm-lintPoint-info": {
|
||||||
|
"&:after": { borderBottomColor: "#999" }
|
||||||
|
},
|
||||||
|
".cm-lintPoint-hint": {
|
||||||
|
"&:after": { borderBottomColor: "#66d" }
|
||||||
|
},
|
||||||
|
".cm-panel.cm-panel-lint": {
|
||||||
|
position: "relative",
|
||||||
|
"& ul": {
|
||||||
|
maxHeight: "100px",
|
||||||
|
overflowY: "auto",
|
||||||
|
"& [aria-selected]": {
|
||||||
|
backgroundColor: "#ddd",
|
||||||
|
"& u": { textDecoration: "underline" }
|
||||||
|
},
|
||||||
|
"&:focus [aria-selected]": {
|
||||||
|
background_fallback: "#bdf",
|
||||||
|
backgroundColor: "Highlight",
|
||||||
|
color_fallback: "white",
|
||||||
|
color: "HighlightText"
|
||||||
|
},
|
||||||
|
"& u": { textDecoration: "none" },
|
||||||
|
padding: 0,
|
||||||
|
margin: 0
|
||||||
|
},
|
||||||
|
"& [name=close]": {
|
||||||
|
position: "absolute",
|
||||||
|
top: "0",
|
||||||
|
right: "2px",
|
||||||
|
background: "inherit",
|
||||||
|
border: "none",
|
||||||
|
font: "inherit",
|
||||||
|
padding: 0,
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"&dark .cm-lintRange-active": { backgroundColor: "#86714a80" },
|
||||||
|
"&dark .cm-panel.cm-panel-lint ul": {
|
||||||
|
"& [aria-selected]": {
|
||||||
|
backgroundColor: "#2e343e",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function severityWeight(sev) {
|
||||||
|
return sev == "error" ? 4 : sev == "warning" ? 3 : sev == "info" ? 2 : 1;
|
||||||
|
}
|
||||||
|
function maxSeverity(diagnostics) {
|
||||||
|
let sev = "hint", weight = 1;
|
||||||
|
for (let d of diagnostics) {
|
||||||
|
let w = severityWeight(d.severity);
|
||||||
|
if (w > weight) {
|
||||||
|
weight = w;
|
||||||
|
sev = d.severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sev;
|
||||||
|
}
|
||||||
|
class LintGutterMarker extends view.GutterMarker {
|
||||||
|
constructor(diagnostics) {
|
||||||
|
super();
|
||||||
|
this.diagnostics = diagnostics;
|
||||||
|
this.severity = maxSeverity(diagnostics);
|
||||||
|
}
|
||||||
|
toDOM(view) {
|
||||||
|
let elt = document.createElement("div");
|
||||||
|
elt.className = "cm-lint-marker cm-lint-marker-" + this.severity;
|
||||||
|
let diagnostics = this.diagnostics;
|
||||||
|
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
||||||
|
if (diagnosticsFilter)
|
||||||
|
diagnostics = diagnosticsFilter(diagnostics, view.state);
|
||||||
|
if (diagnostics.length)
|
||||||
|
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
||||||
|
return elt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function trackHoverOn(view, marker) {
|
||||||
|
let mousemove = (event) => {
|
||||||
|
let rect = marker.getBoundingClientRect();
|
||||||
|
if (event.clientX > rect.left - 10 /* Hover.Margin */ && event.clientX < rect.right + 10 /* Hover.Margin */ &&
|
||||||
|
event.clientY > rect.top - 10 /* Hover.Margin */ && event.clientY < rect.bottom + 10 /* Hover.Margin */)
|
||||||
|
return;
|
||||||
|
for (let target = event.target; target; target = target.parentNode) {
|
||||||
|
if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint"))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.removeEventListener("mousemove", mousemove);
|
||||||
|
if (view.state.field(lintGutterTooltip))
|
||||||
|
view.dispatch({ effects: setLintGutterTooltip.of(null) });
|
||||||
|
};
|
||||||
|
window.addEventListener("mousemove", mousemove);
|
||||||
|
}
|
||||||
|
function gutterMarkerMouseOver(view, marker, diagnostics) {
|
||||||
|
function hovered() {
|
||||||
|
let line = view.elementAtHeight(marker.getBoundingClientRect().top + 5 - view.documentTop);
|
||||||
|
const linePos = view.coordsAtPos(line.from);
|
||||||
|
if (linePos) {
|
||||||
|
view.dispatch({ effects: setLintGutterTooltip.of({
|
||||||
|
pos: line.from,
|
||||||
|
above: false,
|
||||||
|
clip: false,
|
||||||
|
create() {
|
||||||
|
return {
|
||||||
|
dom: diagnosticsTooltip(view, diagnostics),
|
||||||
|
getCoords: () => marker.getBoundingClientRect()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}) });
|
||||||
|
}
|
||||||
|
marker.onmouseout = marker.onmousemove = null;
|
||||||
|
trackHoverOn(view, marker);
|
||||||
|
}
|
||||||
|
let { hoverTime } = view.state.facet(lintGutterConfig);
|
||||||
|
let hoverTimeout = setTimeout(hovered, hoverTime);
|
||||||
|
marker.onmouseout = () => {
|
||||||
|
clearTimeout(hoverTimeout);
|
||||||
|
marker.onmouseout = marker.onmousemove = null;
|
||||||
|
};
|
||||||
|
marker.onmousemove = () => {
|
||||||
|
clearTimeout(hoverTimeout);
|
||||||
|
hoverTimeout = setTimeout(hovered, hoverTime);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function markersForDiagnostics(doc, diagnostics) {
|
||||||
|
let byLine = Object.create(null);
|
||||||
|
for (let diagnostic of diagnostics) {
|
||||||
|
let line = doc.lineAt(diagnostic.from);
|
||||||
|
(byLine[line.from] || (byLine[line.from] = [])).push(diagnostic);
|
||||||
|
}
|
||||||
|
let markers = [];
|
||||||
|
for (let line in byLine) {
|
||||||
|
markers.push(new LintGutterMarker(byLine[line]).range(+line));
|
||||||
|
}
|
||||||
|
return state.RangeSet.of(markers, true);
|
||||||
|
}
|
||||||
|
const lintGutterExtension = view.gutter({
|
||||||
|
class: "cm-gutter-lint",
|
||||||
|
markers: view => view.state.field(lintGutterMarkers),
|
||||||
|
widgetMarker: (view, widget, block) => {
|
||||||
|
let diagnostics = [];
|
||||||
|
view.state.field(lintGutterMarkers).between(block.from, block.to, (from, to, value) => {
|
||||||
|
if (from > block.from && from < block.to)
|
||||||
|
diagnostics.push(...value.diagnostics);
|
||||||
|
});
|
||||||
|
return diagnostics.length ? new LintGutterMarker(diagnostics) : null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const lintGutterMarkers = state.StateField.define({
|
||||||
|
create() {
|
||||||
|
return state.RangeSet.empty;
|
||||||
|
},
|
||||||
|
update(markers, tr) {
|
||||||
|
markers = markers.map(tr.changes);
|
||||||
|
let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter;
|
||||||
|
for (let effect of tr.effects) {
|
||||||
|
if (effect.is(setDiagnosticsEffect)) {
|
||||||
|
let diagnostics = effect.value;
|
||||||
|
if (diagnosticFilter)
|
||||||
|
diagnostics = diagnosticFilter(diagnostics || [], tr.state);
|
||||||
|
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return markers;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const setLintGutterTooltip = state.StateEffect.define();
|
||||||
|
const lintGutterTooltip = state.StateField.define({
|
||||||
|
create() { return null; },
|
||||||
|
update(tooltip, tr) {
|
||||||
|
if (tooltip && tr.docChanged)
|
||||||
|
tooltip = hideTooltip(tr, tooltip) ? null : { ...tooltip, pos: tr.changes.mapPos(tooltip.pos) };
|
||||||
|
return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip);
|
||||||
|
},
|
||||||
|
provide: field => view.showTooltip.from(field)
|
||||||
|
});
|
||||||
|
const lintGutterTheme = view.EditorView.baseTheme({
|
||||||
|
".cm-gutter-lint": {
|
||||||
|
width: "1.4em",
|
||||||
|
"& .cm-gutterElement": {
|
||||||
|
padding: ".2em"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".cm-lint-marker": {
|
||||||
|
width: "1em",
|
||||||
|
height: "1em"
|
||||||
|
},
|
||||||
|
".cm-lint-marker-info": {
|
||||||
|
content: svg(`<path fill="#aaf" stroke="#77e" stroke-width="6" stroke-linejoin="round" d="M5 5L35 5L35 35L5 35Z"/>`)
|
||||||
|
},
|
||||||
|
".cm-lint-marker-warning": {
|
||||||
|
content: svg(`<path fill="#fe8" stroke="#fd7" stroke-width="6" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),
|
||||||
|
},
|
||||||
|
".cm-lint-marker-error": {
|
||||||
|
content: svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const lintExtensions = [
|
||||||
|
lintState,
|
||||||
|
view.EditorView.decorations.compute([lintState], state => {
|
||||||
|
let { selected, panel } = state.field(lintState);
|
||||||
|
return !selected || !panel || selected.from == selected.to ? view.Decoration.none : view.Decoration.set([
|
||||||
|
activeMark.range(selected.from, selected.to)
|
||||||
|
]);
|
||||||
|
}),
|
||||||
|
view.hoverTooltip(lintTooltip, { hideOn: hideTooltip }),
|
||||||
|
baseTheme
|
||||||
|
];
|
||||||
|
const lintGutterConfig = state.Facet.define({
|
||||||
|
combine(configs) {
|
||||||
|
return state.combineConfig(configs, {
|
||||||
|
hoverTime: 300 /* Hover.Time */,
|
||||||
|
markerFilter: null,
|
||||||
|
tooltipFilter: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
Returns an extension that installs a gutter showing markers for
|
||||||
|
each line that has diagnostics, which can be hovered over to see
|
||||||
|
the diagnostics.
|
||||||
|
*/
|
||||||
|
function lintGutter(config = {}) {
|
||||||
|
return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Iterate over the marked diagnostics for the given editor state,
|
||||||
|
calling `f` for each of them. Note that, if the document changed
|
||||||
|
since the diagnostics were created, the `Diagnostic` object will
|
||||||
|
hold the original outdated position, whereas the `to` and `from`
|
||||||
|
arguments hold the diagnostic's current position.
|
||||||
|
*/
|
||||||
|
function forEachDiagnostic(state$1, f) {
|
||||||
|
let lState = state$1.field(lintState, false);
|
||||||
|
if (lState && lState.diagnostics.size) {
|
||||||
|
let pending = [], pendingStart = [], lastEnd = -1;
|
||||||
|
for (let iter = state.RangeSet.iter([lState.diagnostics]);; iter.next()) {
|
||||||
|
for (let i = 0; i < pending.length; i++)
|
||||||
|
if (!iter.value || iter.value.spec.diagnostics.indexOf(pending[i]) < 0) {
|
||||||
|
f(pending[i], pendingStart[i], lastEnd);
|
||||||
|
pending.splice(i, 1);
|
||||||
|
pendingStart.splice(i--, 1);
|
||||||
|
}
|
||||||
|
if (!iter.value)
|
||||||
|
break;
|
||||||
|
for (let d of iter.value.spec.diagnostics)
|
||||||
|
if (pending.indexOf(d) < 0) {
|
||||||
|
pending.push(d);
|
||||||
|
pendingStart.push(iter.from);
|
||||||
|
}
|
||||||
|
lastEnd = iter.to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.closeLintPanel = closeLintPanel;
|
||||||
|
exports.diagnosticCount = diagnosticCount;
|
||||||
|
exports.forEachDiagnostic = forEachDiagnostic;
|
||||||
|
exports.forceLinting = forceLinting;
|
||||||
|
exports.lintGutter = lintGutter;
|
||||||
|
exports.lintKeymap = lintKeymap;
|
||||||
|
exports.linter = linter;
|
||||||
|
exports.nextDiagnostic = nextDiagnostic;
|
||||||
|
exports.openLintPanel = openLintPanel;
|
||||||
|
exports.previousDiagnostic = previousDiagnostic;
|
||||||
|
exports.setDiagnostics = setDiagnostics;
|
||||||
|
exports.setDiagnosticsEffect = setDiagnosticsEffect;
|
||||||
195
editor/node_modules/@codemirror/lint/dist/index.d.cts
generated
vendored
Normal file
195
editor/node_modules/@codemirror/lint/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { EditorState, TransactionSpec, Extension, Transaction } from '@codemirror/state';
|
||||||
|
import { EditorView, Command, KeyBinding, ViewUpdate } from '@codemirror/view';
|
||||||
|
|
||||||
|
type Severity = "hint" | "info" | "warning" | "error";
|
||||||
|
/**
|
||||||
|
Describes a problem or hint for a piece of code.
|
||||||
|
*/
|
||||||
|
interface Diagnostic {
|
||||||
|
/**
|
||||||
|
The start position of the relevant text.
|
||||||
|
*/
|
||||||
|
from: number;
|
||||||
|
/**
|
||||||
|
The end position. May be equal to `from`, though actually
|
||||||
|
covering text is preferable.
|
||||||
|
*/
|
||||||
|
to: number;
|
||||||
|
/**
|
||||||
|
The severity of the problem. This will influence how it is
|
||||||
|
displayed.
|
||||||
|
*/
|
||||||
|
severity: Severity;
|
||||||
|
/**
|
||||||
|
When given, add an extra CSS class to parts of the code that
|
||||||
|
this diagnostic applies to.
|
||||||
|
*/
|
||||||
|
markClass?: string;
|
||||||
|
/**
|
||||||
|
An optional source string indicating where the diagnostic is
|
||||||
|
coming from. You can put the name of your linter here, if
|
||||||
|
applicable.
|
||||||
|
*/
|
||||||
|
source?: string;
|
||||||
|
/**
|
||||||
|
The message associated with this diagnostic.
|
||||||
|
*/
|
||||||
|
message: string;
|
||||||
|
/**
|
||||||
|
An optional custom rendering function that displays the message
|
||||||
|
as a DOM node.
|
||||||
|
*/
|
||||||
|
renderMessage?: (view: EditorView) => Node;
|
||||||
|
/**
|
||||||
|
An optional array of actions that can be taken on this
|
||||||
|
diagnostic.
|
||||||
|
*/
|
||||||
|
actions?: readonly Action[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
An action associated with a diagnostic.
|
||||||
|
*/
|
||||||
|
interface Action {
|
||||||
|
/**
|
||||||
|
The label to show to the user. Should be relatively short.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
When given, add an extra CSS class to the action button.
|
||||||
|
*/
|
||||||
|
markClass?: string;
|
||||||
|
/**
|
||||||
|
The function to call when the user activates this action. Is
|
||||||
|
given the diagnostic's _current_ position, which may have
|
||||||
|
changed since the creation of the diagnostic, due to editing.
|
||||||
|
*/
|
||||||
|
apply: (view: EditorView, from: number, to: number) => void;
|
||||||
|
}
|
||||||
|
type DiagnosticFilter = (diagnostics: readonly Diagnostic[], state: EditorState) => Diagnostic[];
|
||||||
|
interface LintConfig {
|
||||||
|
/**
|
||||||
|
Time to wait (in milliseconds) after a change before running
|
||||||
|
the linter. Defaults to 750ms.
|
||||||
|
*/
|
||||||
|
delay?: number;
|
||||||
|
/**
|
||||||
|
Optional predicate that can be used to indicate when diagnostics
|
||||||
|
need to be recomputed. Linting is always re-done on document
|
||||||
|
changes.
|
||||||
|
*/
|
||||||
|
needsRefresh?: null | ((update: ViewUpdate) => boolean);
|
||||||
|
/**
|
||||||
|
Optional filter to determine which diagnostics produce markers
|
||||||
|
in the content.
|
||||||
|
*/
|
||||||
|
markerFilter?: null | DiagnosticFilter;
|
||||||
|
/**
|
||||||
|
Filter applied to a set of diagnostics shown in a tooltip. No
|
||||||
|
tooltip will appear if the empty set is returned.
|
||||||
|
*/
|
||||||
|
tooltipFilter?: null | DiagnosticFilter;
|
||||||
|
/**
|
||||||
|
Can be used to control what kind of transactions cause lint
|
||||||
|
hover tooltips associated with the given document range to be
|
||||||
|
hidden. By default any transactions that changes the line
|
||||||
|
around the range will hide it. Returning null falls back to this
|
||||||
|
behavior.
|
||||||
|
*/
|
||||||
|
hideOn?: (tr: Transaction, from: number, to: number) => boolean | null;
|
||||||
|
/**
|
||||||
|
When enabled (defaults to off), this will cause the lint panel
|
||||||
|
to automatically open when diagnostics are found, and close when
|
||||||
|
all diagnostics are resolved or removed.
|
||||||
|
*/
|
||||||
|
autoPanel?: boolean;
|
||||||
|
}
|
||||||
|
interface LintGutterConfig {
|
||||||
|
/**
|
||||||
|
The delay before showing a tooltip when hovering over a lint gutter marker.
|
||||||
|
*/
|
||||||
|
hoverTime?: number;
|
||||||
|
/**
|
||||||
|
Optional filter determining which diagnostics show a marker in
|
||||||
|
the gutter.
|
||||||
|
*/
|
||||||
|
markerFilter?: null | DiagnosticFilter;
|
||||||
|
/**
|
||||||
|
Optional filter for diagnostics displayed in a tooltip, which
|
||||||
|
can also be used to prevent a tooltip appearing.
|
||||||
|
*/
|
||||||
|
tooltipFilter?: null | DiagnosticFilter;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Returns a transaction spec which updates the current set of
|
||||||
|
diagnostics, and enables the lint extension if if wasn't already
|
||||||
|
active.
|
||||||
|
*/
|
||||||
|
declare function setDiagnostics(state: EditorState, diagnostics: readonly Diagnostic[]): TransactionSpec;
|
||||||
|
/**
|
||||||
|
The state effect that updates the set of active diagnostics. Can
|
||||||
|
be useful when writing an extension that needs to track these.
|
||||||
|
*/
|
||||||
|
declare const setDiagnosticsEffect: _codemirror_state.StateEffectType<readonly Diagnostic[]>;
|
||||||
|
/**
|
||||||
|
Returns the number of active lint diagnostics in the given state.
|
||||||
|
*/
|
||||||
|
declare function diagnosticCount(state: EditorState): number;
|
||||||
|
/**
|
||||||
|
Command to open and focus the lint panel.
|
||||||
|
*/
|
||||||
|
declare const openLintPanel: Command;
|
||||||
|
/**
|
||||||
|
Command to close the lint panel, when open.
|
||||||
|
*/
|
||||||
|
declare const closeLintPanel: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the next diagnostic.
|
||||||
|
*/
|
||||||
|
declare const nextDiagnostic: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the previous diagnostic.
|
||||||
|
*/
|
||||||
|
declare const previousDiagnostic: Command;
|
||||||
|
/**
|
||||||
|
A set of default key bindings for the lint functionality.
|
||||||
|
|
||||||
|
- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
|
||||||
|
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
||||||
|
*/
|
||||||
|
declare const lintKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
The type of a function that produces diagnostics.
|
||||||
|
*/
|
||||||
|
type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>;
|
||||||
|
/**
|
||||||
|
Given a diagnostic source, this function returns an extension that
|
||||||
|
enables linting with that source. It will be called whenever the
|
||||||
|
editor is idle (after its content changed).
|
||||||
|
|
||||||
|
Note that settings given here will apply to all linters active in
|
||||||
|
the editor. If `null` is given as source, this only configures the
|
||||||
|
lint extension.
|
||||||
|
*/
|
||||||
|
declare function linter(source: LintSource | null, config?: LintConfig): Extension;
|
||||||
|
/**
|
||||||
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
||||||
|
editor is idle to run right away.
|
||||||
|
*/
|
||||||
|
declare function forceLinting(view: EditorView): void;
|
||||||
|
/**
|
||||||
|
Returns an extension that installs a gutter showing markers for
|
||||||
|
each line that has diagnostics, which can be hovered over to see
|
||||||
|
the diagnostics.
|
||||||
|
*/
|
||||||
|
declare function lintGutter(config?: LintGutterConfig): Extension;
|
||||||
|
/**
|
||||||
|
Iterate over the marked diagnostics for the given editor state,
|
||||||
|
calling `f` for each of them. Note that, if the document changed
|
||||||
|
since the diagnostics were created, the `Diagnostic` object will
|
||||||
|
hold the original outdated position, whereas the `to` and `from`
|
||||||
|
arguments hold the diagnostic's current position.
|
||||||
|
*/
|
||||||
|
declare function forEachDiagnostic(state: EditorState, f: (d: Diagnostic, from: number, to: number) => void): void;
|
||||||
|
|
||||||
|
export { type Action, type Diagnostic, type LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
|
||||||
195
editor/node_modules/@codemirror/lint/dist/index.d.ts
generated
vendored
Normal file
195
editor/node_modules/@codemirror/lint/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { EditorState, TransactionSpec, Extension, Transaction } from '@codemirror/state';
|
||||||
|
import { EditorView, Command, KeyBinding, ViewUpdate } from '@codemirror/view';
|
||||||
|
|
||||||
|
type Severity = "hint" | "info" | "warning" | "error";
|
||||||
|
/**
|
||||||
|
Describes a problem or hint for a piece of code.
|
||||||
|
*/
|
||||||
|
interface Diagnostic {
|
||||||
|
/**
|
||||||
|
The start position of the relevant text.
|
||||||
|
*/
|
||||||
|
from: number;
|
||||||
|
/**
|
||||||
|
The end position. May be equal to `from`, though actually
|
||||||
|
covering text is preferable.
|
||||||
|
*/
|
||||||
|
to: number;
|
||||||
|
/**
|
||||||
|
The severity of the problem. This will influence how it is
|
||||||
|
displayed.
|
||||||
|
*/
|
||||||
|
severity: Severity;
|
||||||
|
/**
|
||||||
|
When given, add an extra CSS class to parts of the code that
|
||||||
|
this diagnostic applies to.
|
||||||
|
*/
|
||||||
|
markClass?: string;
|
||||||
|
/**
|
||||||
|
An optional source string indicating where the diagnostic is
|
||||||
|
coming from. You can put the name of your linter here, if
|
||||||
|
applicable.
|
||||||
|
*/
|
||||||
|
source?: string;
|
||||||
|
/**
|
||||||
|
The message associated with this diagnostic.
|
||||||
|
*/
|
||||||
|
message: string;
|
||||||
|
/**
|
||||||
|
An optional custom rendering function that displays the message
|
||||||
|
as a DOM node.
|
||||||
|
*/
|
||||||
|
renderMessage?: (view: EditorView) => Node;
|
||||||
|
/**
|
||||||
|
An optional array of actions that can be taken on this
|
||||||
|
diagnostic.
|
||||||
|
*/
|
||||||
|
actions?: readonly Action[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
An action associated with a diagnostic.
|
||||||
|
*/
|
||||||
|
interface Action {
|
||||||
|
/**
|
||||||
|
The label to show to the user. Should be relatively short.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
When given, add an extra CSS class to the action button.
|
||||||
|
*/
|
||||||
|
markClass?: string;
|
||||||
|
/**
|
||||||
|
The function to call when the user activates this action. Is
|
||||||
|
given the diagnostic's _current_ position, which may have
|
||||||
|
changed since the creation of the diagnostic, due to editing.
|
||||||
|
*/
|
||||||
|
apply: (view: EditorView, from: number, to: number) => void;
|
||||||
|
}
|
||||||
|
type DiagnosticFilter = (diagnostics: readonly Diagnostic[], state: EditorState) => Diagnostic[];
|
||||||
|
interface LintConfig {
|
||||||
|
/**
|
||||||
|
Time to wait (in milliseconds) after a change before running
|
||||||
|
the linter. Defaults to 750ms.
|
||||||
|
*/
|
||||||
|
delay?: number;
|
||||||
|
/**
|
||||||
|
Optional predicate that can be used to indicate when diagnostics
|
||||||
|
need to be recomputed. Linting is always re-done on document
|
||||||
|
changes.
|
||||||
|
*/
|
||||||
|
needsRefresh?: null | ((update: ViewUpdate) => boolean);
|
||||||
|
/**
|
||||||
|
Optional filter to determine which diagnostics produce markers
|
||||||
|
in the content.
|
||||||
|
*/
|
||||||
|
markerFilter?: null | DiagnosticFilter;
|
||||||
|
/**
|
||||||
|
Filter applied to a set of diagnostics shown in a tooltip. No
|
||||||
|
tooltip will appear if the empty set is returned.
|
||||||
|
*/
|
||||||
|
tooltipFilter?: null | DiagnosticFilter;
|
||||||
|
/**
|
||||||
|
Can be used to control what kind of transactions cause lint
|
||||||
|
hover tooltips associated with the given document range to be
|
||||||
|
hidden. By default any transactions that changes the line
|
||||||
|
around the range will hide it. Returning null falls back to this
|
||||||
|
behavior.
|
||||||
|
*/
|
||||||
|
hideOn?: (tr: Transaction, from: number, to: number) => boolean | null;
|
||||||
|
/**
|
||||||
|
When enabled (defaults to off), this will cause the lint panel
|
||||||
|
to automatically open when diagnostics are found, and close when
|
||||||
|
all diagnostics are resolved or removed.
|
||||||
|
*/
|
||||||
|
autoPanel?: boolean;
|
||||||
|
}
|
||||||
|
interface LintGutterConfig {
|
||||||
|
/**
|
||||||
|
The delay before showing a tooltip when hovering over a lint gutter marker.
|
||||||
|
*/
|
||||||
|
hoverTime?: number;
|
||||||
|
/**
|
||||||
|
Optional filter determining which diagnostics show a marker in
|
||||||
|
the gutter.
|
||||||
|
*/
|
||||||
|
markerFilter?: null | DiagnosticFilter;
|
||||||
|
/**
|
||||||
|
Optional filter for diagnostics displayed in a tooltip, which
|
||||||
|
can also be used to prevent a tooltip appearing.
|
||||||
|
*/
|
||||||
|
tooltipFilter?: null | DiagnosticFilter;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Returns a transaction spec which updates the current set of
|
||||||
|
diagnostics, and enables the lint extension if if wasn't already
|
||||||
|
active.
|
||||||
|
*/
|
||||||
|
declare function setDiagnostics(state: EditorState, diagnostics: readonly Diagnostic[]): TransactionSpec;
|
||||||
|
/**
|
||||||
|
The state effect that updates the set of active diagnostics. Can
|
||||||
|
be useful when writing an extension that needs to track these.
|
||||||
|
*/
|
||||||
|
declare const setDiagnosticsEffect: _codemirror_state.StateEffectType<readonly Diagnostic[]>;
|
||||||
|
/**
|
||||||
|
Returns the number of active lint diagnostics in the given state.
|
||||||
|
*/
|
||||||
|
declare function diagnosticCount(state: EditorState): number;
|
||||||
|
/**
|
||||||
|
Command to open and focus the lint panel.
|
||||||
|
*/
|
||||||
|
declare const openLintPanel: Command;
|
||||||
|
/**
|
||||||
|
Command to close the lint panel, when open.
|
||||||
|
*/
|
||||||
|
declare const closeLintPanel: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the next diagnostic.
|
||||||
|
*/
|
||||||
|
declare const nextDiagnostic: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the previous diagnostic.
|
||||||
|
*/
|
||||||
|
declare const previousDiagnostic: Command;
|
||||||
|
/**
|
||||||
|
A set of default key bindings for the lint functionality.
|
||||||
|
|
||||||
|
- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
|
||||||
|
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
||||||
|
*/
|
||||||
|
declare const lintKeymap: readonly KeyBinding[];
|
||||||
|
/**
|
||||||
|
The type of a function that produces diagnostics.
|
||||||
|
*/
|
||||||
|
type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>;
|
||||||
|
/**
|
||||||
|
Given a diagnostic source, this function returns an extension that
|
||||||
|
enables linting with that source. It will be called whenever the
|
||||||
|
editor is idle (after its content changed).
|
||||||
|
|
||||||
|
Note that settings given here will apply to all linters active in
|
||||||
|
the editor. If `null` is given as source, this only configures the
|
||||||
|
lint extension.
|
||||||
|
*/
|
||||||
|
declare function linter(source: LintSource | null, config?: LintConfig): Extension;
|
||||||
|
/**
|
||||||
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
||||||
|
editor is idle to run right away.
|
||||||
|
*/
|
||||||
|
declare function forceLinting(view: EditorView): void;
|
||||||
|
/**
|
||||||
|
Returns an extension that installs a gutter showing markers for
|
||||||
|
each line that has diagnostics, which can be hovered over to see
|
||||||
|
the diagnostics.
|
||||||
|
*/
|
||||||
|
declare function lintGutter(config?: LintGutterConfig): Extension;
|
||||||
|
/**
|
||||||
|
Iterate over the marked diagnostics for the given editor state,
|
||||||
|
calling `f` for each of them. Note that, if the document changed
|
||||||
|
since the diagnostics were created, the `Diagnostic` object will
|
||||||
|
hold the original outdated position, whereas the `to` and `from`
|
||||||
|
arguments hold the diagnostic's current position.
|
||||||
|
*/
|
||||||
|
declare function forEachDiagnostic(state: EditorState, f: (d: Diagnostic, from: number, to: number) => void): void;
|
||||||
|
|
||||||
|
export { type Action, type Diagnostic, type LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
|
||||||
945
editor/node_modules/@codemirror/lint/dist/index.js
generated
vendored
Normal file
945
editor/node_modules/@codemirror/lint/dist/index.js
generated
vendored
Normal file
@@ -0,0 +1,945 @@
|
|||||||
|
import { Decoration, showPanel, EditorView, ViewPlugin, gutter, showTooltip, hoverTooltip, getPanel, logException, WidgetType, GutterMarker } from '@codemirror/view';
|
||||||
|
import { StateEffect, StateField, Facet, combineConfig, RangeSet, RangeSetBuilder } from '@codemirror/state';
|
||||||
|
import elt from 'crelt';
|
||||||
|
|
||||||
|
class SelectedDiagnostic {
|
||||||
|
constructor(from, to, diagnostic) {
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.diagnostic = diagnostic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class LintState {
|
||||||
|
constructor(diagnostics, panel, selected) {
|
||||||
|
this.diagnostics = diagnostics;
|
||||||
|
this.panel = panel;
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
static init(diagnostics, panel, state) {
|
||||||
|
// Filter the list of diagnostics for which to create markers
|
||||||
|
let diagnosticFilter = state.facet(lintConfig).markerFilter;
|
||||||
|
if (diagnosticFilter)
|
||||||
|
diagnostics = diagnosticFilter(diagnostics, state);
|
||||||
|
let sorted = diagnostics.slice().sort((a, b) => a.from - b.from || a.to - b.to);
|
||||||
|
let deco = new RangeSetBuilder(), active = [], pos = 0;
|
||||||
|
let scan = state.doc.iter(), scanPos = 0, docLen = state.doc.length;
|
||||||
|
for (let i = 0;;) {
|
||||||
|
let next = i == sorted.length ? null : sorted[i];
|
||||||
|
if (!next && !active.length)
|
||||||
|
break;
|
||||||
|
let from, to;
|
||||||
|
if (active.length) {
|
||||||
|
from = pos;
|
||||||
|
to = active.reduce((p, d) => Math.min(p, d.to), next && next.from > from ? next.from : 1e8);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
from = next.from;
|
||||||
|
if (from > docLen)
|
||||||
|
break;
|
||||||
|
to = next.to;
|
||||||
|
active.push(next);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (i < sorted.length) {
|
||||||
|
let next = sorted[i];
|
||||||
|
if (next.from == from && (next.to > next.from || next.to == from)) {
|
||||||
|
active.push(next);
|
||||||
|
i++;
|
||||||
|
to = Math.min(next.to, to);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
to = Math.min(next.from, to);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to = Math.min(to, docLen);
|
||||||
|
let widget = false;
|
||||||
|
if (active.some(d => d.from == from && (d.to == to || to == docLen))) {
|
||||||
|
widget = from == to;
|
||||||
|
if (!widget && to - from < 10) {
|
||||||
|
let behind = from - (scanPos + scan.value.length);
|
||||||
|
if (behind > 0) {
|
||||||
|
scan.next(behind);
|
||||||
|
scanPos = from;
|
||||||
|
}
|
||||||
|
for (let check = from;;) {
|
||||||
|
if (check >= to) {
|
||||||
|
widget = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!scan.lineBreak && scanPos + scan.value.length > check)
|
||||||
|
break;
|
||||||
|
check = scanPos + scan.value.length;
|
||||||
|
scanPos += scan.value.length;
|
||||||
|
scan.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let sev = maxSeverity(active);
|
||||||
|
if (widget) {
|
||||||
|
deco.add(from, from, Decoration.widget({
|
||||||
|
widget: new DiagnosticWidget(sev),
|
||||||
|
diagnostics: active.slice()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let markClass = active.reduce((c, d) => d.markClass ? c + " " + d.markClass : c, "");
|
||||||
|
deco.add(from, to, Decoration.mark({
|
||||||
|
class: "cm-lintRange cm-lintRange-" + sev + markClass,
|
||||||
|
diagnostics: active.slice(),
|
||||||
|
inclusiveEnd: active.some(a => a.to > to)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
pos = to;
|
||||||
|
if (pos == docLen)
|
||||||
|
break;
|
||||||
|
for (let i = 0; i < active.length; i++)
|
||||||
|
if (active[i].to <= pos)
|
||||||
|
active.splice(i--, 1);
|
||||||
|
}
|
||||||
|
let set = deco.finish();
|
||||||
|
return new LintState(set, panel, findDiagnostic(set));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
|
||||||
|
let found = null;
|
||||||
|
diagnostics.between(after, 1e9, (from, to, { spec }) => {
|
||||||
|
if (diagnostic && spec.diagnostics.indexOf(diagnostic) < 0)
|
||||||
|
return;
|
||||||
|
if (!found)
|
||||||
|
found = new SelectedDiagnostic(from, to, diagnostic || spec.diagnostics[0]);
|
||||||
|
else if (spec.diagnostics.indexOf(found.diagnostic) < 0)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
found = new SelectedDiagnostic(found.from, to, found.diagnostic);
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
function hideTooltip(tr, tooltip) {
|
||||||
|
let from = tooltip.pos, to = tooltip.end || from;
|
||||||
|
let result = tr.state.facet(lintConfig).hideOn(tr, from, to);
|
||||||
|
if (result != null)
|
||||||
|
return result;
|
||||||
|
let line = tr.startState.doc.lineAt(tooltip.pos);
|
||||||
|
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, Math.max(line.to, to)));
|
||||||
|
}
|
||||||
|
function maybeEnableLint(state, effects) {
|
||||||
|
return state.field(lintState, false) ? effects : effects.concat(StateEffect.appendConfig.of(lintExtensions));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Returns a transaction spec which updates the current set of
|
||||||
|
diagnostics, and enables the lint extension if if wasn't already
|
||||||
|
active.
|
||||||
|
*/
|
||||||
|
function setDiagnostics(state, diagnostics) {
|
||||||
|
return {
|
||||||
|
effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
The state effect that updates the set of active diagnostics. Can
|
||||||
|
be useful when writing an extension that needs to track these.
|
||||||
|
*/
|
||||||
|
const setDiagnosticsEffect = /*@__PURE__*/StateEffect.define();
|
||||||
|
const togglePanel = /*@__PURE__*/StateEffect.define();
|
||||||
|
const movePanelSelection = /*@__PURE__*/StateEffect.define();
|
||||||
|
const lintState = /*@__PURE__*/StateField.define({
|
||||||
|
create() {
|
||||||
|
return new LintState(Decoration.none, null, null);
|
||||||
|
},
|
||||||
|
update(value, tr) {
|
||||||
|
if (tr.docChanged && value.diagnostics.size) {
|
||||||
|
let mapped = value.diagnostics.map(tr.changes), selected = null, panel = value.panel;
|
||||||
|
if (value.selected) {
|
||||||
|
let selPos = tr.changes.mapPos(value.selected.from, 1);
|
||||||
|
selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos);
|
||||||
|
}
|
||||||
|
if (!mapped.size && panel && tr.state.facet(lintConfig).autoPanel)
|
||||||
|
panel = null;
|
||||||
|
value = new LintState(mapped, panel, selected);
|
||||||
|
}
|
||||||
|
for (let effect of tr.effects) {
|
||||||
|
if (effect.is(setDiagnosticsEffect)) {
|
||||||
|
let panel = !tr.state.facet(lintConfig).autoPanel ? value.panel : effect.value.length ? LintPanel.open : null;
|
||||||
|
value = LintState.init(effect.value, panel, tr.state);
|
||||||
|
}
|
||||||
|
else if (effect.is(togglePanel)) {
|
||||||
|
value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected);
|
||||||
|
}
|
||||||
|
else if (effect.is(movePanelSelection)) {
|
||||||
|
value = new LintState(value.diagnostics, value.panel, effect.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
provide: f => [showPanel.from(f, val => val.panel),
|
||||||
|
EditorView.decorations.from(f, s => s.diagnostics)]
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
Returns the number of active lint diagnostics in the given state.
|
||||||
|
*/
|
||||||
|
function diagnosticCount(state) {
|
||||||
|
let lint = state.field(lintState, false);
|
||||||
|
return lint ? lint.diagnostics.size : 0;
|
||||||
|
}
|
||||||
|
const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
|
||||||
|
function lintTooltip(view, pos, side) {
|
||||||
|
let { diagnostics } = view.state.field(lintState);
|
||||||
|
let found, start = -1, end = -1;
|
||||||
|
diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => {
|
||||||
|
if (pos >= from && pos <= to &&
|
||||||
|
(from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) {
|
||||||
|
found = spec.diagnostics;
|
||||||
|
start = from;
|
||||||
|
end = to;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
||||||
|
if (found && diagnosticFilter)
|
||||||
|
found = diagnosticFilter(found, view.state);
|
||||||
|
if (!found)
|
||||||
|
return null;
|
||||||
|
return {
|
||||||
|
pos: start,
|
||||||
|
end: end,
|
||||||
|
above: view.state.doc.lineAt(start).to < end,
|
||||||
|
create() {
|
||||||
|
return { dom: diagnosticsTooltip(view, found) };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function diagnosticsTooltip(view, diagnostics) {
|
||||||
|
return elt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false)));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Command to open and focus the lint panel.
|
||||||
|
*/
|
||||||
|
const openLintPanel = (view) => {
|
||||||
|
let field = view.state.field(lintState, false);
|
||||||
|
if (!field || !field.panel)
|
||||||
|
view.dispatch({ effects: maybeEnableLint(view.state, [togglePanel.of(true)]) });
|
||||||
|
let panel = getPanel(view, LintPanel.open);
|
||||||
|
if (panel)
|
||||||
|
panel.dom.querySelector(".cm-panel-lint ul").focus();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Command to close the lint panel, when open.
|
||||||
|
*/
|
||||||
|
const closeLintPanel = (view) => {
|
||||||
|
let field = view.state.field(lintState, false);
|
||||||
|
if (!field || !field.panel)
|
||||||
|
return false;
|
||||||
|
view.dispatch({ effects: togglePanel.of(false) });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Move the selection to the next diagnostic.
|
||||||
|
*/
|
||||||
|
const nextDiagnostic = (view) => {
|
||||||
|
let field = view.state.field(lintState, false);
|
||||||
|
if (!field)
|
||||||
|
return false;
|
||||||
|
let sel = view.state.selection.main, next = findDiagnostic(field.diagnostics, null, sel.to + 1);
|
||||||
|
if (!next) {
|
||||||
|
next = findDiagnostic(field.diagnostics, null, 0);
|
||||||
|
if (!next || next.from == sel.from && next.to == sel.to)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
view.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Move the selection to the previous diagnostic.
|
||||||
|
*/
|
||||||
|
const previousDiagnostic = (view) => {
|
||||||
|
let { state } = view, field = state.field(lintState, false);
|
||||||
|
if (!field)
|
||||||
|
return false;
|
||||||
|
let sel = state.selection.main;
|
||||||
|
let prevFrom, prevTo, lastFrom, lastTo;
|
||||||
|
field.diagnostics.between(0, state.doc.length, (from, to) => {
|
||||||
|
if (to < sel.to && (prevFrom == null || prevFrom < from)) {
|
||||||
|
prevFrom = from;
|
||||||
|
prevTo = to;
|
||||||
|
}
|
||||||
|
if (lastFrom == null || from > lastFrom) {
|
||||||
|
lastFrom = from;
|
||||||
|
lastTo = to;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (lastFrom == null || prevFrom == null && lastFrom == sel.from)
|
||||||
|
return false;
|
||||||
|
view.dispatch({ selection: { anchor: prevFrom !== null && prevFrom !== void 0 ? prevFrom : lastFrom, head: prevTo !== null && prevTo !== void 0 ? prevTo : lastTo }, scrollIntoView: true });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
A set of default key bindings for the lint functionality.
|
||||||
|
|
||||||
|
- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
|
||||||
|
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
||||||
|
*/
|
||||||
|
const lintKeymap = [
|
||||||
|
{ key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
|
||||||
|
{ key: "F8", run: nextDiagnostic }
|
||||||
|
];
|
||||||
|
const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
||||||
|
constructor(view) {
|
||||||
|
this.view = view;
|
||||||
|
this.timeout = -1;
|
||||||
|
this.set = true;
|
||||||
|
let { delay } = view.state.facet(lintConfig);
|
||||||
|
this.lintTime = Date.now() + delay;
|
||||||
|
this.run = this.run.bind(this);
|
||||||
|
this.timeout = setTimeout(this.run, delay);
|
||||||
|
}
|
||||||
|
run() {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
let now = Date.now();
|
||||||
|
if (now < this.lintTime - 10) {
|
||||||
|
this.timeout = setTimeout(this.run, this.lintTime - now);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.set = false;
|
||||||
|
let { state } = this.view, { sources } = state.facet(lintConfig);
|
||||||
|
if (sources.length)
|
||||||
|
batchResults(sources.map(s => Promise.resolve(s(this.view))), annotations => {
|
||||||
|
if (this.view.state.doc == state.doc)
|
||||||
|
this.view.dispatch(setDiagnostics(this.view.state, annotations.reduce((a, b) => a.concat(b))));
|
||||||
|
}, error => { logException(this.view.state, error); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update(update) {
|
||||||
|
let config = update.state.facet(lintConfig);
|
||||||
|
if (update.docChanged || config != update.startState.facet(lintConfig) ||
|
||||||
|
config.needsRefresh && config.needsRefresh(update)) {
|
||||||
|
this.lintTime = Date.now() + config.delay;
|
||||||
|
if (!this.set) {
|
||||||
|
this.set = true;
|
||||||
|
this.timeout = setTimeout(this.run, config.delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
force() {
|
||||||
|
if (this.set) {
|
||||||
|
this.lintTime = Date.now();
|
||||||
|
this.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function batchResults(promises, sink, error) {
|
||||||
|
let collected = [], timeout = -1;
|
||||||
|
for (let p of promises)
|
||||||
|
p.then(value => {
|
||||||
|
collected.push(value);
|
||||||
|
clearTimeout(timeout);
|
||||||
|
if (collected.length == promises.length)
|
||||||
|
sink(collected);
|
||||||
|
else
|
||||||
|
timeout = setTimeout(() => sink(collected), 200);
|
||||||
|
}, error);
|
||||||
|
}
|
||||||
|
const lintConfig = /*@__PURE__*/Facet.define({
|
||||||
|
combine(input) {
|
||||||
|
return {
|
||||||
|
sources: input.map(i => i.source).filter(x => x != null),
|
||||||
|
...combineConfig(input.map(i => i.config), {
|
||||||
|
delay: 750,
|
||||||
|
markerFilter: null,
|
||||||
|
tooltipFilter: null,
|
||||||
|
needsRefresh: null,
|
||||||
|
hideOn: () => null,
|
||||||
|
}, {
|
||||||
|
delay: Math.max,
|
||||||
|
markerFilter: combineFilter,
|
||||||
|
tooltipFilter: combineFilter,
|
||||||
|
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u),
|
||||||
|
hideOn: (a, b) => !a ? b : !b ? a : (t, x, y) => a(t, x, y) || b(t, x, y),
|
||||||
|
autoPanel: (a, b) => a || b
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function combineFilter(a, b) {
|
||||||
|
return !a ? b : !b ? a : (d, s) => b(a(d, s), s);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Given a diagnostic source, this function returns an extension that
|
||||||
|
enables linting with that source. It will be called whenever the
|
||||||
|
editor is idle (after its content changed).
|
||||||
|
|
||||||
|
Note that settings given here will apply to all linters active in
|
||||||
|
the editor. If `null` is given as source, this only configures the
|
||||||
|
lint extension.
|
||||||
|
*/
|
||||||
|
function linter(source, config = {}) {
|
||||||
|
return [
|
||||||
|
lintConfig.of({ source, config }),
|
||||||
|
lintPlugin,
|
||||||
|
lintExtensions
|
||||||
|
];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
||||||
|
editor is idle to run right away.
|
||||||
|
*/
|
||||||
|
function forceLinting(view) {
|
||||||
|
let plugin = view.plugin(lintPlugin);
|
||||||
|
if (plugin)
|
||||||
|
plugin.force();
|
||||||
|
}
|
||||||
|
function assignKeys(actions) {
|
||||||
|
let assigned = [];
|
||||||
|
if (actions)
|
||||||
|
actions: for (let { name } of actions) {
|
||||||
|
for (let i = 0; i < name.length; i++) {
|
||||||
|
let ch = name[i];
|
||||||
|
if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) {
|
||||||
|
assigned.push(ch);
|
||||||
|
continue actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assigned.push("");
|
||||||
|
}
|
||||||
|
return assigned;
|
||||||
|
}
|
||||||
|
function renderDiagnostic(view, diagnostic, inPanel) {
|
||||||
|
var _a;
|
||||||
|
let keys = inPanel ? assignKeys(diagnostic.actions) : [];
|
||||||
|
return elt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, elt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage(view) : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {
|
||||||
|
let fired = false, click = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (fired)
|
||||||
|
return;
|
||||||
|
fired = true;
|
||||||
|
let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
|
||||||
|
if (found)
|
||||||
|
action.apply(view, found.from, found.to);
|
||||||
|
};
|
||||||
|
let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1;
|
||||||
|
let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
|
||||||
|
elt("u", name.slice(keyIndex, keyIndex + 1)),
|
||||||
|
name.slice(keyIndex + 1)];
|
||||||
|
let markClass = action.markClass ? " " + action.markClass : "";
|
||||||
|
return elt("button", {
|
||||||
|
type: "button",
|
||||||
|
class: "cm-diagnosticAction" + markClass,
|
||||||
|
onclick: click,
|
||||||
|
onmousedown: click,
|
||||||
|
"aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
|
||||||
|
}, nameElt);
|
||||||
|
}), diagnostic.source && elt("div", { class: "cm-diagnosticSource" }, diagnostic.source));
|
||||||
|
}
|
||||||
|
class DiagnosticWidget extends WidgetType {
|
||||||
|
constructor(sev) {
|
||||||
|
super();
|
||||||
|
this.sev = sev;
|
||||||
|
}
|
||||||
|
eq(other) { return other.sev == this.sev; }
|
||||||
|
toDOM() {
|
||||||
|
return elt("span", { class: "cm-lintPoint cm-lintPoint-" + this.sev });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class PanelItem {
|
||||||
|
constructor(view, diagnostic) {
|
||||||
|
this.diagnostic = diagnostic;
|
||||||
|
this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16);
|
||||||
|
this.dom = renderDiagnostic(view, diagnostic, true);
|
||||||
|
this.dom.id = this.id;
|
||||||
|
this.dom.setAttribute("role", "option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class LintPanel {
|
||||||
|
constructor(view) {
|
||||||
|
this.view = view;
|
||||||
|
this.items = [];
|
||||||
|
let onkeydown = (event) => {
|
||||||
|
if (event.ctrlKey || event.altKey || event.metaKey)
|
||||||
|
return;
|
||||||
|
if (event.keyCode == 27) { // Escape
|
||||||
|
closeLintPanel(this.view);
|
||||||
|
this.view.focus();
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp
|
||||||
|
this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown
|
||||||
|
this.moveSelection((this.selectedIndex + 1) % this.items.length);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 36) { // Home
|
||||||
|
this.moveSelection(0);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 35) { // End
|
||||||
|
this.moveSelection(this.items.length - 1);
|
||||||
|
}
|
||||||
|
else if (event.keyCode == 13) { // Enter
|
||||||
|
this.view.focus();
|
||||||
|
}
|
||||||
|
else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z
|
||||||
|
let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions);
|
||||||
|
for (let i = 0; i < keys.length; i++)
|
||||||
|
if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) {
|
||||||
|
let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic);
|
||||||
|
if (found)
|
||||||
|
diagnostic.actions[i].apply(view, found.from, found.to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
};
|
||||||
|
let onclick = (event) => {
|
||||||
|
for (let i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].dom.contains(event.target))
|
||||||
|
this.moveSelection(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.list = elt("ul", {
|
||||||
|
tabIndex: 0,
|
||||||
|
role: "listbox",
|
||||||
|
"aria-label": this.view.state.phrase("Diagnostics"),
|
||||||
|
onkeydown,
|
||||||
|
onclick
|
||||||
|
});
|
||||||
|
this.dom = elt("div", { class: "cm-panel-lint" }, this.list, elt("button", {
|
||||||
|
type: "button",
|
||||||
|
name: "close",
|
||||||
|
"aria-label": this.view.state.phrase("close"),
|
||||||
|
onclick: () => closeLintPanel(this.view)
|
||||||
|
}, "×"));
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
get selectedIndex() {
|
||||||
|
let selected = this.view.state.field(lintState).selected;
|
||||||
|
if (!selected)
|
||||||
|
return -1;
|
||||||
|
for (let i = 0; i < this.items.length; i++)
|
||||||
|
if (this.items[i].diagnostic == selected.diagnostic)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
update() {
|
||||||
|
let { diagnostics, selected } = this.view.state.field(lintState);
|
||||||
|
let i = 0, needsSync = false, newSelectedItem = null;
|
||||||
|
let seen = new Set();
|
||||||
|
diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => {
|
||||||
|
for (let diagnostic of spec.diagnostics) {
|
||||||
|
if (seen.has(diagnostic))
|
||||||
|
continue;
|
||||||
|
seen.add(diagnostic);
|
||||||
|
let found = -1, item;
|
||||||
|
for (let j = i; j < this.items.length; j++)
|
||||||
|
if (this.items[j].diagnostic == diagnostic) {
|
||||||
|
found = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (found < 0) {
|
||||||
|
item = new PanelItem(this.view, diagnostic);
|
||||||
|
this.items.splice(i, 0, item);
|
||||||
|
needsSync = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
item = this.items[found];
|
||||||
|
if (found > i) {
|
||||||
|
this.items.splice(i, found - i);
|
||||||
|
needsSync = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selected && item.diagnostic == selected.diagnostic) {
|
||||||
|
if (!item.dom.hasAttribute("aria-selected")) {
|
||||||
|
item.dom.setAttribute("aria-selected", "true");
|
||||||
|
newSelectedItem = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (item.dom.hasAttribute("aria-selected")) {
|
||||||
|
item.dom.removeAttribute("aria-selected");
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) {
|
||||||
|
needsSync = true;
|
||||||
|
this.items.pop();
|
||||||
|
}
|
||||||
|
if (this.items.length == 0) {
|
||||||
|
this.items.push(new PanelItem(this.view, {
|
||||||
|
from: -1, to: -1,
|
||||||
|
severity: "info",
|
||||||
|
message: this.view.state.phrase("No diagnostics")
|
||||||
|
}));
|
||||||
|
needsSync = true;
|
||||||
|
}
|
||||||
|
if (newSelectedItem) {
|
||||||
|
this.list.setAttribute("aria-activedescendant", newSelectedItem.id);
|
||||||
|
this.view.requestMeasure({
|
||||||
|
key: this,
|
||||||
|
read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }),
|
||||||
|
write: ({ sel, panel }) => {
|
||||||
|
let scaleY = panel.height / this.list.offsetHeight;
|
||||||
|
if (sel.top < panel.top)
|
||||||
|
this.list.scrollTop -= (panel.top - sel.top) / scaleY;
|
||||||
|
else if (sel.bottom > panel.bottom)
|
||||||
|
this.list.scrollTop += (sel.bottom - panel.bottom) / scaleY;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (this.selectedIndex < 0) {
|
||||||
|
this.list.removeAttribute("aria-activedescendant");
|
||||||
|
}
|
||||||
|
if (needsSync)
|
||||||
|
this.sync();
|
||||||
|
}
|
||||||
|
sync() {
|
||||||
|
let domPos = this.list.firstChild;
|
||||||
|
function rm() {
|
||||||
|
let prev = domPos;
|
||||||
|
domPos = prev.nextSibling;
|
||||||
|
prev.remove();
|
||||||
|
}
|
||||||
|
for (let item of this.items) {
|
||||||
|
if (item.dom.parentNode == this.list) {
|
||||||
|
while (domPos != item.dom)
|
||||||
|
rm();
|
||||||
|
domPos = item.dom.nextSibling;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.list.insertBefore(item.dom, domPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (domPos)
|
||||||
|
rm();
|
||||||
|
}
|
||||||
|
moveSelection(selectedIndex) {
|
||||||
|
if (this.selectedIndex < 0)
|
||||||
|
return;
|
||||||
|
let field = this.view.state.field(lintState);
|
||||||
|
let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic);
|
||||||
|
if (!selection)
|
||||||
|
return;
|
||||||
|
this.view.dispatch({
|
||||||
|
selection: { anchor: selection.from, head: selection.to },
|
||||||
|
scrollIntoView: true,
|
||||||
|
effects: movePanelSelection.of(selection)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
static open(view) { return new LintPanel(view); }
|
||||||
|
}
|
||||||
|
function svg(content, attrs = `viewBox="0 0 40 40"`) {
|
||||||
|
return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
|
||||||
|
}
|
||||||
|
function underline(color) {
|
||||||
|
return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, `width="6" height="3"`);
|
||||||
|
}
|
||||||
|
const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
||||||
|
".cm-diagnostic": {
|
||||||
|
padding: "3px 6px 3px 8px",
|
||||||
|
marginLeft: "-1px",
|
||||||
|
display: "block",
|
||||||
|
whiteSpace: "pre-wrap"
|
||||||
|
},
|
||||||
|
".cm-diagnostic-error": { borderLeft: "5px solid #d11" },
|
||||||
|
".cm-diagnostic-warning": { borderLeft: "5px solid orange" },
|
||||||
|
".cm-diagnostic-info": { borderLeft: "5px solid #999" },
|
||||||
|
".cm-diagnostic-hint": { borderLeft: "5px solid #66d" },
|
||||||
|
".cm-diagnosticAction": {
|
||||||
|
font: "inherit",
|
||||||
|
border: "none",
|
||||||
|
padding: "2px 4px",
|
||||||
|
backgroundColor: "#444",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "3px",
|
||||||
|
marginLeft: "8px",
|
||||||
|
cursor: "pointer"
|
||||||
|
},
|
||||||
|
".cm-diagnosticSource": {
|
||||||
|
fontSize: "70%",
|
||||||
|
opacity: .7
|
||||||
|
},
|
||||||
|
".cm-lintRange": {
|
||||||
|
backgroundPosition: "left bottom",
|
||||||
|
backgroundRepeat: "repeat-x",
|
||||||
|
paddingBottom: "0.7px",
|
||||||
|
},
|
||||||
|
".cm-lintRange-error": { backgroundImage: /*@__PURE__*/underline("#d11") },
|
||||||
|
".cm-lintRange-warning": { backgroundImage: /*@__PURE__*/underline("orange") },
|
||||||
|
".cm-lintRange-info": { backgroundImage: /*@__PURE__*/underline("#999") },
|
||||||
|
".cm-lintRange-hint": { backgroundImage: /*@__PURE__*/underline("#66d") },
|
||||||
|
".cm-lintRange-active": { backgroundColor: "#ffdd9980" },
|
||||||
|
".cm-tooltip-lint": {
|
||||||
|
padding: 0,
|
||||||
|
margin: 0
|
||||||
|
},
|
||||||
|
".cm-lintPoint": {
|
||||||
|
position: "relative",
|
||||||
|
"&:after": {
|
||||||
|
content: '""',
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 0,
|
||||||
|
left: "-2px",
|
||||||
|
borderLeft: "3px solid transparent",
|
||||||
|
borderRight: "3px solid transparent",
|
||||||
|
borderBottom: "4px solid #d11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".cm-lintPoint-warning": {
|
||||||
|
"&:after": { borderBottomColor: "orange" }
|
||||||
|
},
|
||||||
|
".cm-lintPoint-info": {
|
||||||
|
"&:after": { borderBottomColor: "#999" }
|
||||||
|
},
|
||||||
|
".cm-lintPoint-hint": {
|
||||||
|
"&:after": { borderBottomColor: "#66d" }
|
||||||
|
},
|
||||||
|
".cm-panel.cm-panel-lint": {
|
||||||
|
position: "relative",
|
||||||
|
"& ul": {
|
||||||
|
maxHeight: "100px",
|
||||||
|
overflowY: "auto",
|
||||||
|
"& [aria-selected]": {
|
||||||
|
backgroundColor: "#ddd",
|
||||||
|
"& u": { textDecoration: "underline" }
|
||||||
|
},
|
||||||
|
"&:focus [aria-selected]": {
|
||||||
|
background_fallback: "#bdf",
|
||||||
|
backgroundColor: "Highlight",
|
||||||
|
color_fallback: "white",
|
||||||
|
color: "HighlightText"
|
||||||
|
},
|
||||||
|
"& u": { textDecoration: "none" },
|
||||||
|
padding: 0,
|
||||||
|
margin: 0
|
||||||
|
},
|
||||||
|
"& [name=close]": {
|
||||||
|
position: "absolute",
|
||||||
|
top: "0",
|
||||||
|
right: "2px",
|
||||||
|
background: "inherit",
|
||||||
|
border: "none",
|
||||||
|
font: "inherit",
|
||||||
|
padding: 0,
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"&dark .cm-lintRange-active": { backgroundColor: "#86714a80" },
|
||||||
|
"&dark .cm-panel.cm-panel-lint ul": {
|
||||||
|
"& [aria-selected]": {
|
||||||
|
backgroundColor: "#2e343e",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function severityWeight(sev) {
|
||||||
|
return sev == "error" ? 4 : sev == "warning" ? 3 : sev == "info" ? 2 : 1;
|
||||||
|
}
|
||||||
|
function maxSeverity(diagnostics) {
|
||||||
|
let sev = "hint", weight = 1;
|
||||||
|
for (let d of diagnostics) {
|
||||||
|
let w = severityWeight(d.severity);
|
||||||
|
if (w > weight) {
|
||||||
|
weight = w;
|
||||||
|
sev = d.severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sev;
|
||||||
|
}
|
||||||
|
class LintGutterMarker extends GutterMarker {
|
||||||
|
constructor(diagnostics) {
|
||||||
|
super();
|
||||||
|
this.diagnostics = diagnostics;
|
||||||
|
this.severity = maxSeverity(diagnostics);
|
||||||
|
}
|
||||||
|
toDOM(view) {
|
||||||
|
let elt = document.createElement("div");
|
||||||
|
elt.className = "cm-lint-marker cm-lint-marker-" + this.severity;
|
||||||
|
let diagnostics = this.diagnostics;
|
||||||
|
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
||||||
|
if (diagnosticsFilter)
|
||||||
|
diagnostics = diagnosticsFilter(diagnostics, view.state);
|
||||||
|
if (diagnostics.length)
|
||||||
|
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
||||||
|
return elt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function trackHoverOn(view, marker) {
|
||||||
|
let mousemove = (event) => {
|
||||||
|
let rect = marker.getBoundingClientRect();
|
||||||
|
if (event.clientX > rect.left - 10 /* Hover.Margin */ && event.clientX < rect.right + 10 /* Hover.Margin */ &&
|
||||||
|
event.clientY > rect.top - 10 /* Hover.Margin */ && event.clientY < rect.bottom + 10 /* Hover.Margin */)
|
||||||
|
return;
|
||||||
|
for (let target = event.target; target; target = target.parentNode) {
|
||||||
|
if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint"))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.removeEventListener("mousemove", mousemove);
|
||||||
|
if (view.state.field(lintGutterTooltip))
|
||||||
|
view.dispatch({ effects: setLintGutterTooltip.of(null) });
|
||||||
|
};
|
||||||
|
window.addEventListener("mousemove", mousemove);
|
||||||
|
}
|
||||||
|
function gutterMarkerMouseOver(view, marker, diagnostics) {
|
||||||
|
function hovered() {
|
||||||
|
let line = view.elementAtHeight(marker.getBoundingClientRect().top + 5 - view.documentTop);
|
||||||
|
const linePos = view.coordsAtPos(line.from);
|
||||||
|
if (linePos) {
|
||||||
|
view.dispatch({ effects: setLintGutterTooltip.of({
|
||||||
|
pos: line.from,
|
||||||
|
above: false,
|
||||||
|
clip: false,
|
||||||
|
create() {
|
||||||
|
return {
|
||||||
|
dom: diagnosticsTooltip(view, diagnostics),
|
||||||
|
getCoords: () => marker.getBoundingClientRect()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}) });
|
||||||
|
}
|
||||||
|
marker.onmouseout = marker.onmousemove = null;
|
||||||
|
trackHoverOn(view, marker);
|
||||||
|
}
|
||||||
|
let { hoverTime } = view.state.facet(lintGutterConfig);
|
||||||
|
let hoverTimeout = setTimeout(hovered, hoverTime);
|
||||||
|
marker.onmouseout = () => {
|
||||||
|
clearTimeout(hoverTimeout);
|
||||||
|
marker.onmouseout = marker.onmousemove = null;
|
||||||
|
};
|
||||||
|
marker.onmousemove = () => {
|
||||||
|
clearTimeout(hoverTimeout);
|
||||||
|
hoverTimeout = setTimeout(hovered, hoverTime);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function markersForDiagnostics(doc, diagnostics) {
|
||||||
|
let byLine = Object.create(null);
|
||||||
|
for (let diagnostic of diagnostics) {
|
||||||
|
let line = doc.lineAt(diagnostic.from);
|
||||||
|
(byLine[line.from] || (byLine[line.from] = [])).push(diagnostic);
|
||||||
|
}
|
||||||
|
let markers = [];
|
||||||
|
for (let line in byLine) {
|
||||||
|
markers.push(new LintGutterMarker(byLine[line]).range(+line));
|
||||||
|
}
|
||||||
|
return RangeSet.of(markers, true);
|
||||||
|
}
|
||||||
|
const lintGutterExtension = /*@__PURE__*/gutter({
|
||||||
|
class: "cm-gutter-lint",
|
||||||
|
markers: view => view.state.field(lintGutterMarkers),
|
||||||
|
widgetMarker: (view, widget, block) => {
|
||||||
|
let diagnostics = [];
|
||||||
|
view.state.field(lintGutterMarkers).between(block.from, block.to, (from, to, value) => {
|
||||||
|
if (from > block.from && from < block.to)
|
||||||
|
diagnostics.push(...value.diagnostics);
|
||||||
|
});
|
||||||
|
return diagnostics.length ? new LintGutterMarker(diagnostics) : null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const lintGutterMarkers = /*@__PURE__*/StateField.define({
|
||||||
|
create() {
|
||||||
|
return RangeSet.empty;
|
||||||
|
},
|
||||||
|
update(markers, tr) {
|
||||||
|
markers = markers.map(tr.changes);
|
||||||
|
let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter;
|
||||||
|
for (let effect of tr.effects) {
|
||||||
|
if (effect.is(setDiagnosticsEffect)) {
|
||||||
|
let diagnostics = effect.value;
|
||||||
|
if (diagnosticFilter)
|
||||||
|
diagnostics = diagnosticFilter(diagnostics || [], tr.state);
|
||||||
|
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return markers;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const setLintGutterTooltip = /*@__PURE__*/StateEffect.define();
|
||||||
|
const lintGutterTooltip = /*@__PURE__*/StateField.define({
|
||||||
|
create() { return null; },
|
||||||
|
update(tooltip, tr) {
|
||||||
|
if (tooltip && tr.docChanged)
|
||||||
|
tooltip = hideTooltip(tr, tooltip) ? null : { ...tooltip, pos: tr.changes.mapPos(tooltip.pos) };
|
||||||
|
return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip);
|
||||||
|
},
|
||||||
|
provide: field => showTooltip.from(field)
|
||||||
|
});
|
||||||
|
const lintGutterTheme = /*@__PURE__*/EditorView.baseTheme({
|
||||||
|
".cm-gutter-lint": {
|
||||||
|
width: "1.4em",
|
||||||
|
"& .cm-gutterElement": {
|
||||||
|
padding: ".2em"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".cm-lint-marker": {
|
||||||
|
width: "1em",
|
||||||
|
height: "1em"
|
||||||
|
},
|
||||||
|
".cm-lint-marker-info": {
|
||||||
|
content: /*@__PURE__*/svg(`<path fill="#aaf" stroke="#77e" stroke-width="6" stroke-linejoin="round" d="M5 5L35 5L35 35L5 35Z"/>`)
|
||||||
|
},
|
||||||
|
".cm-lint-marker-warning": {
|
||||||
|
content: /*@__PURE__*/svg(`<path fill="#fe8" stroke="#fd7" stroke-width="6" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),
|
||||||
|
},
|
||||||
|
".cm-lint-marker-error": {
|
||||||
|
content: /*@__PURE__*/svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const lintExtensions = [
|
||||||
|
lintState,
|
||||||
|
/*@__PURE__*/EditorView.decorations.compute([lintState], state => {
|
||||||
|
let { selected, panel } = state.field(lintState);
|
||||||
|
return !selected || !panel || selected.from == selected.to ? Decoration.none : Decoration.set([
|
||||||
|
activeMark.range(selected.from, selected.to)
|
||||||
|
]);
|
||||||
|
}),
|
||||||
|
/*@__PURE__*/hoverTooltip(lintTooltip, { hideOn: hideTooltip }),
|
||||||
|
baseTheme
|
||||||
|
];
|
||||||
|
const lintGutterConfig = /*@__PURE__*/Facet.define({
|
||||||
|
combine(configs) {
|
||||||
|
return combineConfig(configs, {
|
||||||
|
hoverTime: 300 /* Hover.Time */,
|
||||||
|
markerFilter: null,
|
||||||
|
tooltipFilter: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
Returns an extension that installs a gutter showing markers for
|
||||||
|
each line that has diagnostics, which can be hovered over to see
|
||||||
|
the diagnostics.
|
||||||
|
*/
|
||||||
|
function lintGutter(config = {}) {
|
||||||
|
return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Iterate over the marked diagnostics for the given editor state,
|
||||||
|
calling `f` for each of them. Note that, if the document changed
|
||||||
|
since the diagnostics were created, the `Diagnostic` object will
|
||||||
|
hold the original outdated position, whereas the `to` and `from`
|
||||||
|
arguments hold the diagnostic's current position.
|
||||||
|
*/
|
||||||
|
function forEachDiagnostic(state, f) {
|
||||||
|
let lState = state.field(lintState, false);
|
||||||
|
if (lState && lState.diagnostics.size) {
|
||||||
|
let pending = [], pendingStart = [], lastEnd = -1;
|
||||||
|
for (let iter = RangeSet.iter([lState.diagnostics]);; iter.next()) {
|
||||||
|
for (let i = 0; i < pending.length; i++)
|
||||||
|
if (!iter.value || iter.value.spec.diagnostics.indexOf(pending[i]) < 0) {
|
||||||
|
f(pending[i], pendingStart[i], lastEnd);
|
||||||
|
pending.splice(i, 1);
|
||||||
|
pendingStart.splice(i--, 1);
|
||||||
|
}
|
||||||
|
if (!iter.value)
|
||||||
|
break;
|
||||||
|
for (let d of iter.value.spec.diagnostics)
|
||||||
|
if (pending.indexOf(d) < 0) {
|
||||||
|
pending.push(d);
|
||||||
|
pendingStart.push(iter.from);
|
||||||
|
}
|
||||||
|
lastEnd = iter.to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
|
||||||
40
editor/node_modules/@codemirror/lint/package.json
generated
vendored
Normal file
40
editor/node_modules/@codemirror/lint/package.json
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "@codemirror/lint",
|
||||||
|
"version": "6.9.5",
|
||||||
|
"description": "Linting support for the CodeMirror code editor",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cm-runtests",
|
||||||
|
"prepare": "cm-buildhelper src/lint.ts"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"code"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Marijn Haverbeke",
|
||||||
|
"email": "marijn@haverbeke.berlin",
|
||||||
|
"url": "http://marijnhaverbeke.nl"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"sideEffects": false,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.35.0",
|
||||||
|
"crelt": "^1.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/buildhelper": "^1.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/codemirror/lint.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
16
editor/node_modules/@codemirror/search/.github/workflows/dispatch.yml
generated
vendored
Normal file
16
editor/node_modules/@codemirror/search/.github/workflows/dispatch.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Trigger CI
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Dispatch to main repo
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Emit repository_dispatch
|
||||||
|
uses: mvasigh/dispatch-action@main
|
||||||
|
with:
|
||||||
|
# You should create a personal access token and store it in your repository
|
||||||
|
token: ${{ secrets.DISPATCH_AUTH }}
|
||||||
|
repo: dev
|
||||||
|
owner: codemirror
|
||||||
|
event_type: push
|
||||||
324
editor/node_modules/@codemirror/search/CHANGELOG.md
generated
vendored
Normal file
324
editor/node_modules/@codemirror/search/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
## 6.6.0 (2026-01-13)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Search queries now support a generic `test` field that can be used to implement custom tests on matches.
|
||||||
|
|
||||||
|
## 6.5.11 (2025-05-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue in `replaceNext` that could cause it to create an invalid selection when replacing past the end of the document.
|
||||||
|
|
||||||
|
## 6.5.10 (2025-02-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Add a close button to the `gotoLine` panel.
|
||||||
|
|
||||||
|
## 6.5.9 (2025-02-12)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
When replacing a regexp match, don't expand multi-digit replacement markers to numbers beyond the captured group count in the query.
|
||||||
|
|
||||||
|
## 6.5.8 (2024-11-22)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that put the selection in the wrong place after running `replaceNext` with a regexp query that could match strings of different length.
|
||||||
|
|
||||||
|
## 6.5.7 (2024-11-01)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where `findNext` and `findPrevious` would do nothing when the only match in the document was partially selected.
|
||||||
|
|
||||||
|
Fix an infinite loop in `SearchCursor` when the normalizer function deletes characters.
|
||||||
|
|
||||||
|
## 6.5.6 (2024-02-07)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `highlightSelectionMatches` include whitespace in the selection in its matches.
|
||||||
|
|
||||||
|
Fix a bug that caused `SearchCursor` to return invalid ranges when matching astral chars that the the normalizer normalized to single-code-unit chars.
|
||||||
|
|
||||||
|
## 6.5.5 (2023-11-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused codes like `\n` to be unescaped in strings inserted via replace placeholders like `$&`.
|
||||||
|
|
||||||
|
Use the keybinding Mod-Alt-g for `gotoLine` to the search keymap, to make it usable for people whose keyboard layout uses Alt/Option-g to type some character.
|
||||||
|
|
||||||
|
## 6.5.4 (2023-09-20)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused whole-word search to incorrectly check for word boundaries in some circumstances.
|
||||||
|
|
||||||
|
## 6.5.3 (2023-09-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
The `gotoLine` dialog is now populated with the current line number when you open it.
|
||||||
|
|
||||||
|
## 6.5.2 (2023-08-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't use the very lowest precedence for match highlighting decorations.
|
||||||
|
|
||||||
|
## 6.5.1 (2023-08-04)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `gotoLine` prefer to scroll the target line to the middle of the view.
|
||||||
|
|
||||||
|
Fix an issue in `SearchCursor` where character normalization could produce nonsensical matches.
|
||||||
|
|
||||||
|
## 6.5.0 (2023-06-05)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `regexp` option to `search` can be used to control whether queries have the regexp flag on by default.
|
||||||
|
|
||||||
|
## 6.4.0 (2023-04-25)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
The `findNext` and `findPrevious` commands now select the search field text if that field is focused.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `scrollToMatch` callback option now receives the editor view as a second parameter.
|
||||||
|
|
||||||
|
## 6.3.0 (2023-03-20)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `scrollToMatch` search option allows you to adjust the way the editor scrolls search matches into view.
|
||||||
|
|
||||||
|
## 6.2.3 (2022-11-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that hid the search dialog's close button when the editor was read-only.
|
||||||
|
|
||||||
|
## 6.2.2 (2022-10-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
When `literal` is off, \n, \r, and \t escapes are now also supported in replacement text.
|
||||||
|
|
||||||
|
Make sure search dialog inputs don't get treated as form fields when the editor is created inside a form.
|
||||||
|
|
||||||
|
Fix a bug in `RegExpCursor` that would cause it to stop matching in the middle of a line when its current match position was equal to the length of the line.
|
||||||
|
|
||||||
|
## 6.2.1 (2022-09-26)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
By-word search queries will now skip any result that had word characters both before and after a match boundary.
|
||||||
|
|
||||||
|
## 6.2.0 (2022-08-25)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
A new `wholeWord` search query flag can be used to limit matches to whole words.
|
||||||
|
|
||||||
|
`SearchCursor` and `RegExpCursor` now support a `test` parameter that can be used to ignore certain matches.
|
||||||
|
|
||||||
|
## 6.1.0 (2022-08-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an infinite loop when the match position of a `RegExpCursor` ended up in the middle of an UTF16 surrogate pair.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `literal` search option can now be set to make literal queries the default.
|
||||||
|
|
||||||
|
The new `searchPanelOpen` function can be used to find out whether the search panel is open for a given state.
|
||||||
|
|
||||||
|
## 6.0.1 (2022-07-22)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
`findNext` and `findPrevious` will now return to the current result (and scroll it into view) if no other matches are found.
|
||||||
|
|
||||||
|
## 6.0.0 (2022-06-08)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Don't crash when a custom search panel doesn't have a field named 'search'.
|
||||||
|
|
||||||
|
Make sure replacements are announced to screen readers.
|
||||||
|
|
||||||
|
## 0.20.1 (2022-04-22)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
It is now possible to disable backslash escapes in search queries with the `literal` option.
|
||||||
|
|
||||||
|
## 0.20.0 (2022-04-20)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make the `wholeWords` option to `highlightSelectionMatches` default to false, as intended.
|
||||||
|
|
||||||
|
## 0.19.10 (2022-04-04)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure search matches are highlighted when scrolling new content into view.
|
||||||
|
|
||||||
|
## 0.19.9 (2022-03-03)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The selection-matching extension now accepts a `wholeWords` option that makes it only highlight matches that span a whole word. Add SearchQuery.getCursor
|
||||||
|
|
||||||
|
The `SearchQuery` class now has a `getCursor` method that allows external code to create a cursor for the query.
|
||||||
|
|
||||||
|
## 0.19.8 (2022-02-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused the search panel to start open when configuring a state with the `search()` extension.
|
||||||
|
|
||||||
|
## 0.19.7 (2022-02-14)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
`searchConfig` is deprecated in favor of `search` (but will exist until next major release).
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `search` function is now used to enable and configure the search extension.
|
||||||
|
|
||||||
|
## 0.19.6 (2022-01-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `selectNextOccurrence` scroll the newly selected range into view.
|
||||||
|
|
||||||
|
## 0.19.5 (2021-12-16)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
The search option `matchCase` was renamed to `caseSensitive` (the old name will continue to work until the next breaking release).
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
`openSearchPanel` will now update the search query to the current selection even if the panel was already open.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Client code can now pass a custom search panel creation function in the search configuration.
|
||||||
|
|
||||||
|
The `getSearchQuery` function and `setSearchQuery` effect can now be used to inspect or change the current search query.
|
||||||
|
|
||||||
|
## 0.19.4 (2021-12-02)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
The search panel will no longer show the replace interface when the editor is read-only.
|
||||||
|
|
||||||
|
## 0.19.3 (2021-11-22)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Add `userEvent` annotations to search and replace transactions.
|
||||||
|
|
||||||
|
Make sure the editor handles keys bound to `findNext`/`findPrevious` even when there are no matches, to avoid the browser's search interrupting users.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Add a `Symbol.iterator` property to the cursor types, so that they can be used with `for`/`of`.
|
||||||
|
|
||||||
|
## 0.19.2 (2021-09-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
`selectNextOccurrence` will now only select partial words if the current main selection hold a partial word.
|
||||||
|
|
||||||
|
Explicitly set the button's type to prevent the browser from submitting forms wrapped around the editor.
|
||||||
|
|
||||||
|
## 0.19.1 (2021-09-06)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `highlightSelectionMatches` not produce overlapping decorations, since those tend to just get unreadable.
|
||||||
|
|
||||||
|
Make sure any existing search text is selected when opening the search panel. Add search config option to not match case when search panel is opened (#4)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `searchConfig` function now takes a `matchCase` option that controls whether the search panel starts in case-sensitive mode.
|
||||||
|
|
||||||
|
## 0.19.0 (2021-08-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure to prevent the native Mod-d behavior so that the editor doesn't lose focus after selecting past the last occurrence.
|
||||||
|
|
||||||
|
## 0.18.4 (2021-05-27)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Initialize the search query to the current selection, when there is one, when opening the search dialog.
|
||||||
|
|
||||||
|
Add a `searchConfig` function, supporting an option to put the search panel at the top of the editor.
|
||||||
|
|
||||||
|
## 0.18.3 (2021-05-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where the first search command in a new editor wouldn't properly open the panel.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
New command `selectNextOccurrence` that selects the next occurrence of the selected word (bound to Mod-d in the search keymap).
|
||||||
|
|
||||||
|
## 0.18.2 (2021-03-19)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
The search interface and cursor will no longer include overlapping matches (aligning with what all other editors are doing).
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now exports a `RegExpCursor` which is a search cursor that matches regular expression patterns.
|
||||||
|
|
||||||
|
The search/replace interface now allows the user to use regular expressions.
|
||||||
|
|
||||||
|
The `SearchCursor` class now has a `nextOverlapping` method that includes matches that start inside the previous match.
|
||||||
|
|
||||||
|
Basic backslash escapes (\n, \r, \t, and \\) are now accepted in string search patterns in the UI.
|
||||||
|
|
||||||
|
## 0.18.1 (2021-03-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where entering an invalid input in the goto-line dialog would submit a form and reload the page.
|
||||||
|
|
||||||
|
## 0.18.0 (2021-03-03)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 0.18.
|
||||||
|
|
||||||
|
## 0.17.1 (2021-01-06)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now also exports a CommonJS module.
|
||||||
|
|
||||||
|
## 0.17.0 (2020-12-29)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
First numbered release.
|
||||||
|
|
||||||
21
editor/node_modules/@codemirror/search/LICENSE
generated
vendored
Normal file
21
editor/node_modules/@codemirror/search/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
18
editor/node_modules/@codemirror/search/README.md
generated
vendored
Normal file
18
editor/node_modules/@codemirror/search/README.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# @codemirror/search [](https://www.npmjs.org/package/@codemirror/search)
|
||||||
|
|
||||||
|
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#search) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/search/blob/main/CHANGELOG.md) ]
|
||||||
|
|
||||||
|
This package implements search functionality for the
|
||||||
|
[CodeMirror](https://codemirror.net/) code editor.
|
||||||
|
|
||||||
|
The [project page](https://codemirror.net/) has more information, a
|
||||||
|
number of [examples](https://codemirror.net/examples/) and the
|
||||||
|
[documentation](https://codemirror.net/docs/).
|
||||||
|
|
||||||
|
This code is released under an
|
||||||
|
[MIT license](https://github.com/codemirror/search/tree/main/LICENSE).
|
||||||
|
|
||||||
|
We aim to be an inclusive, welcoming community. To make that explicit,
|
||||||
|
we have a [code of
|
||||||
|
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
||||||
|
to communication around the project.
|
||||||
1237
editor/node_modules/@codemirror/search/dist/index.cjs
generated
vendored
Normal file
1237
editor/node_modules/@codemirror/search/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
385
editor/node_modules/@codemirror/search/dist/index.d.cts
generated
vendored
Normal file
385
editor/node_modules/@codemirror/search/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { Text, Extension, StateCommand, EditorState, SelectionRange, StateEffect } from '@codemirror/state';
|
||||||
|
import { Command, KeyBinding, EditorView, Panel } from '@codemirror/view';
|
||||||
|
|
||||||
|
/**
|
||||||
|
A search cursor provides an iterator over text matches in a
|
||||||
|
document.
|
||||||
|
*/
|
||||||
|
declare class SearchCursor implements Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
}> {
|
||||||
|
private test?;
|
||||||
|
private iter;
|
||||||
|
/**
|
||||||
|
The current match (only holds a meaningful value after
|
||||||
|
[`next`](https://codemirror.net/6/docs/ref/#search.SearchCursor.next) has been called and when
|
||||||
|
`done` is false).
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Whether the end of the iterated region has been reached.
|
||||||
|
*/
|
||||||
|
done: boolean;
|
||||||
|
private matches;
|
||||||
|
private buffer;
|
||||||
|
private bufferPos;
|
||||||
|
private bufferStart;
|
||||||
|
private normalize;
|
||||||
|
private query;
|
||||||
|
/**
|
||||||
|
Create a text cursor. The query is the search string, `from` to
|
||||||
|
`to` provides the region to search.
|
||||||
|
|
||||||
|
When `normalize` is given, it will be called, on both the query
|
||||||
|
string and the content it is matched against, before comparing.
|
||||||
|
You can, for example, create a case-insensitive search by
|
||||||
|
passing `s => s.toLowerCase()`.
|
||||||
|
|
||||||
|
Text is always normalized with
|
||||||
|
[`.normalize("NFKD")`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
||||||
|
(when supported).
|
||||||
|
*/
|
||||||
|
constructor(text: Text, query: string, from?: number, to?: number, normalize?: (string: string) => string, test?: ((from: number, to: number, buffer: string, bufferPos: number) => boolean) | undefined);
|
||||||
|
private peek;
|
||||||
|
/**
|
||||||
|
Look for the next match. Updates the iterator's
|
||||||
|
[`value`](https://codemirror.net/6/docs/ref/#search.SearchCursor.value) and
|
||||||
|
[`done`](https://codemirror.net/6/docs/ref/#search.SearchCursor.done) properties. Should be called
|
||||||
|
at least once before using the cursor.
|
||||||
|
*/
|
||||||
|
next(): this;
|
||||||
|
/**
|
||||||
|
The `next` method will ignore matches that partially overlap a
|
||||||
|
previous match. This method behaves like `next`, but includes
|
||||||
|
such matches.
|
||||||
|
*/
|
||||||
|
nextOverlapping(): this;
|
||||||
|
private match;
|
||||||
|
[Symbol.iterator]: () => Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RegExpCursorOptions {
|
||||||
|
ignoreCase?: boolean;
|
||||||
|
test?: (from: number, to: number, match: RegExpExecArray) => boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
This class is similar to [`SearchCursor`](https://codemirror.net/6/docs/ref/#search.SearchCursor)
|
||||||
|
but searches for a regular expression pattern instead of a plain
|
||||||
|
string.
|
||||||
|
*/
|
||||||
|
declare class RegExpCursor implements Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
match: RegExpExecArray;
|
||||||
|
}> {
|
||||||
|
private text;
|
||||||
|
private to;
|
||||||
|
private iter;
|
||||||
|
private re;
|
||||||
|
private test?;
|
||||||
|
private curLine;
|
||||||
|
private curLineStart;
|
||||||
|
private matchPos;
|
||||||
|
/**
|
||||||
|
Set to `true` when the cursor has reached the end of the search
|
||||||
|
range.
|
||||||
|
*/
|
||||||
|
done: boolean;
|
||||||
|
/**
|
||||||
|
Will contain an object with the extent of the match and the
|
||||||
|
match object when [`next`](https://codemirror.net/6/docs/ref/#search.RegExpCursor.next)
|
||||||
|
sucessfully finds a match.
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
match: RegExpExecArray;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Create a cursor that will search the given range in the given
|
||||||
|
document. `query` should be the raw pattern (as you'd pass it to
|
||||||
|
`new RegExp`).
|
||||||
|
*/
|
||||||
|
constructor(text: Text, query: string, options?: RegExpCursorOptions, from?: number, to?: number);
|
||||||
|
private getLine;
|
||||||
|
private nextLine;
|
||||||
|
/**
|
||||||
|
Move to the next match, if there is one.
|
||||||
|
*/
|
||||||
|
next(): this;
|
||||||
|
[Symbol.iterator]: () => Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
match: RegExpExecArray;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Command that shows a dialog asking the user for a line number, and
|
||||||
|
when a valid position is provided, moves the cursor to that line.
|
||||||
|
|
||||||
|
Supports line numbers, relative line offsets prefixed with `+` or
|
||||||
|
`-`, document percentages suffixed with `%`, and an optional
|
||||||
|
column position by adding `:` and a second number after the line
|
||||||
|
number.
|
||||||
|
*/
|
||||||
|
declare const gotoLine: Command;
|
||||||
|
|
||||||
|
type HighlightOptions = {
|
||||||
|
/**
|
||||||
|
Determines whether, when nothing is selected, the word around
|
||||||
|
the cursor is matched instead. Defaults to false.
|
||||||
|
*/
|
||||||
|
highlightWordAroundCursor?: boolean;
|
||||||
|
/**
|
||||||
|
The minimum length of the selection before it is highlighted.
|
||||||
|
Defaults to 1 (always highlight non-cursor selections).
|
||||||
|
*/
|
||||||
|
minSelectionLength?: number;
|
||||||
|
/**
|
||||||
|
The amount of matches (in the viewport) at which to disable
|
||||||
|
highlighting. Defaults to 100.
|
||||||
|
*/
|
||||||
|
maxMatches?: number;
|
||||||
|
/**
|
||||||
|
Whether to only highlight whole words.
|
||||||
|
*/
|
||||||
|
wholeWords?: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
This extension highlights text that matches the selection. It uses
|
||||||
|
the `"cm-selectionMatch"` class for the highlighting. When
|
||||||
|
`highlightWordAroundCursor` is enabled, the word at the cursor
|
||||||
|
itself will be highlighted with `"cm-selectionMatch-main"`.
|
||||||
|
*/
|
||||||
|
declare function highlightSelectionMatches(options?: HighlightOptions): Extension;
|
||||||
|
/**
|
||||||
|
Select next occurrence of the current selection. Expand selection
|
||||||
|
to the surrounding word when the selection is empty.
|
||||||
|
*/
|
||||||
|
declare const selectNextOccurrence: StateCommand;
|
||||||
|
|
||||||
|
interface SearchConfig {
|
||||||
|
/**
|
||||||
|
Whether to position the search panel at the top of the editor
|
||||||
|
(the default is at the bottom).
|
||||||
|
*/
|
||||||
|
top?: boolean;
|
||||||
|
/**
|
||||||
|
Whether to enable case sensitivity by default when the search
|
||||||
|
panel is activated (defaults to false).
|
||||||
|
*/
|
||||||
|
caseSensitive?: boolean;
|
||||||
|
/**
|
||||||
|
Whether to treat string searches literally by default (defaults to false).
|
||||||
|
*/
|
||||||
|
literal?: boolean;
|
||||||
|
/**
|
||||||
|
Controls whether the default query has by-word matching enabled.
|
||||||
|
Defaults to false.
|
||||||
|
*/
|
||||||
|
wholeWord?: boolean;
|
||||||
|
/**
|
||||||
|
Used to turn on regular expression search in the default query.
|
||||||
|
Defaults to false.
|
||||||
|
*/
|
||||||
|
regexp?: boolean;
|
||||||
|
/**
|
||||||
|
Can be used to override the way the search panel is implemented.
|
||||||
|
Should create a [Panel](https://codemirror.net/6/docs/ref/#view.Panel) that contains a form
|
||||||
|
which lets the user:
|
||||||
|
|
||||||
|
- See the [current](https://codemirror.net/6/docs/ref/#search.getSearchQuery) search query.
|
||||||
|
- Manipulate the [query](https://codemirror.net/6/docs/ref/#search.SearchQuery) and
|
||||||
|
[update](https://codemirror.net/6/docs/ref/#search.setSearchQuery) the search state with a new
|
||||||
|
query.
|
||||||
|
- Notice external changes to the query by reacting to the
|
||||||
|
appropriate [state effect](https://codemirror.net/6/docs/ref/#search.setSearchQuery).
|
||||||
|
- Run some of the search commands.
|
||||||
|
|
||||||
|
The field that should be focused when opening the panel must be
|
||||||
|
tagged with a `main-field=true` DOM attribute.
|
||||||
|
*/
|
||||||
|
createPanel?: (view: EditorView) => Panel;
|
||||||
|
/**
|
||||||
|
By default, matches are scrolled into view using the default
|
||||||
|
behavior of
|
||||||
|
[`EditorView.scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView).
|
||||||
|
This option allows you to pass a custom function to produce the
|
||||||
|
scroll effect.
|
||||||
|
*/
|
||||||
|
scrollToMatch?: (range: SelectionRange, view: EditorView) => StateEffect<unknown>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Add search state to the editor configuration, and optionally
|
||||||
|
configure the search extension.
|
||||||
|
([`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) will automatically
|
||||||
|
enable this if it isn't already on).
|
||||||
|
*/
|
||||||
|
declare function search(config?: SearchConfig): Extension;
|
||||||
|
/**
|
||||||
|
A search query. Part of the editor's search state.
|
||||||
|
*/
|
||||||
|
declare class SearchQuery {
|
||||||
|
/**
|
||||||
|
The search string (or regular expression).
|
||||||
|
*/
|
||||||
|
readonly search: string;
|
||||||
|
/**
|
||||||
|
Indicates whether the search is case-sensitive.
|
||||||
|
*/
|
||||||
|
readonly caseSensitive: boolean;
|
||||||
|
/**
|
||||||
|
By default, string search will replace `\n`, `\r`, and `\t` in
|
||||||
|
the query with newline, return, and tab characters. When this
|
||||||
|
is set to true, that behavior is disabled.
|
||||||
|
*/
|
||||||
|
readonly literal: boolean;
|
||||||
|
/**
|
||||||
|
When true, the search string is interpreted as a regular
|
||||||
|
expression.
|
||||||
|
*/
|
||||||
|
readonly regexp: boolean;
|
||||||
|
/**
|
||||||
|
The replace text, or the empty string if no replace text has
|
||||||
|
been given.
|
||||||
|
*/
|
||||||
|
readonly replace: string;
|
||||||
|
/**
|
||||||
|
Whether this query is non-empty and, in case of a regular
|
||||||
|
expression search, syntactically valid.
|
||||||
|
*/
|
||||||
|
readonly valid: boolean;
|
||||||
|
/**
|
||||||
|
When true, matches that contain words are ignored when there are
|
||||||
|
further word characters around them.
|
||||||
|
*/
|
||||||
|
readonly wholeWord: boolean;
|
||||||
|
/**
|
||||||
|
Optional test function used to filter matches.
|
||||||
|
*/
|
||||||
|
readonly test: ((match: string, state: EditorState, from: number, to: number) => boolean) | undefined;
|
||||||
|
/**
|
||||||
|
Create a query object.
|
||||||
|
*/
|
||||||
|
constructor(config: {
|
||||||
|
/**
|
||||||
|
The search string.
|
||||||
|
*/
|
||||||
|
search: string;
|
||||||
|
/**
|
||||||
|
Controls whether the search should be case-sensitive.
|
||||||
|
*/
|
||||||
|
caseSensitive?: boolean;
|
||||||
|
/**
|
||||||
|
By default, string search will replace `\n`, `\r`, and `\t` in
|
||||||
|
the query with newline, return, and tab characters. When this
|
||||||
|
is set to true, that behavior is disabled.
|
||||||
|
*/
|
||||||
|
literal?: boolean;
|
||||||
|
/**
|
||||||
|
When true, interpret the search string as a regular expression.
|
||||||
|
*/
|
||||||
|
regexp?: boolean;
|
||||||
|
/**
|
||||||
|
The replace text.
|
||||||
|
*/
|
||||||
|
replace?: string;
|
||||||
|
/**
|
||||||
|
Enable whole-word matching.
|
||||||
|
*/
|
||||||
|
wholeWord?: boolean;
|
||||||
|
/**
|
||||||
|
Optional custom filter. It is passed the matched string, the
|
||||||
|
editor state, and the match range. Matches for which it
|
||||||
|
returns false will be ignored.
|
||||||
|
*/
|
||||||
|
test?: (match: string, state: EditorState, from: number, to: number) => boolean;
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
Compare this query to another query.
|
||||||
|
*/
|
||||||
|
eq(other: SearchQuery): boolean;
|
||||||
|
/**
|
||||||
|
Get a search cursor for this query, searching through the given
|
||||||
|
range in the given state.
|
||||||
|
*/
|
||||||
|
getCursor(state: EditorState | Text, from?: number, to?: number): Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
A state effect that updates the current search query. Note that
|
||||||
|
this only has an effect if the search state has been initialized
|
||||||
|
(by including [`search`](https://codemirror.net/6/docs/ref/#search.search) in your configuration or
|
||||||
|
by running [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) at least
|
||||||
|
once).
|
||||||
|
*/
|
||||||
|
declare const setSearchQuery: _codemirror_state.StateEffectType<SearchQuery>;
|
||||||
|
/**
|
||||||
|
Get the current search query from an editor state.
|
||||||
|
*/
|
||||||
|
declare function getSearchQuery(state: EditorState): SearchQuery;
|
||||||
|
/**
|
||||||
|
Query whether the search panel is open in the given editor state.
|
||||||
|
*/
|
||||||
|
declare function searchPanelOpen(state: EditorState): boolean;
|
||||||
|
/**
|
||||||
|
Open the search panel if it isn't already open, and move the
|
||||||
|
selection to the first match after the current main selection.
|
||||||
|
Will wrap around to the start of the document when it reaches the
|
||||||
|
end.
|
||||||
|
*/
|
||||||
|
declare const findNext: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the previous instance of the search query,
|
||||||
|
before the current main selection. Will wrap past the start
|
||||||
|
of the document to start searching at the end again.
|
||||||
|
*/
|
||||||
|
declare const findPrevious: Command;
|
||||||
|
/**
|
||||||
|
Select all instances of the search query.
|
||||||
|
*/
|
||||||
|
declare const selectMatches: Command;
|
||||||
|
/**
|
||||||
|
Select all instances of the currently selected text.
|
||||||
|
*/
|
||||||
|
declare const selectSelectionMatches: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace the current match of the search query.
|
||||||
|
*/
|
||||||
|
declare const replaceNext: Command;
|
||||||
|
/**
|
||||||
|
Replace all instances of the search query with the given
|
||||||
|
replacement.
|
||||||
|
*/
|
||||||
|
declare const replaceAll: Command;
|
||||||
|
/**
|
||||||
|
Make sure the search panel is open and focused.
|
||||||
|
*/
|
||||||
|
declare const openSearchPanel: Command;
|
||||||
|
/**
|
||||||
|
Close the search panel.
|
||||||
|
*/
|
||||||
|
declare const closeSearchPanel: Command;
|
||||||
|
/**
|
||||||
|
Default search-related key bindings.
|
||||||
|
|
||||||
|
- Mod-f: [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel)
|
||||||
|
- F3, Mod-g: [`findNext`](https://codemirror.net/6/docs/ref/#search.findNext)
|
||||||
|
- Shift-F3, Shift-Mod-g: [`findPrevious`](https://codemirror.net/6/docs/ref/#search.findPrevious)
|
||||||
|
- Mod-Alt-g: [`gotoLine`](https://codemirror.net/6/docs/ref/#search.gotoLine)
|
||||||
|
- Mod-d: [`selectNextOccurrence`](https://codemirror.net/6/docs/ref/#search.selectNextOccurrence)
|
||||||
|
*/
|
||||||
|
declare const searchKeymap: readonly KeyBinding[];
|
||||||
|
|
||||||
|
export { RegExpCursor, SearchCursor, SearchQuery, closeSearchPanel, findNext, findPrevious, getSearchQuery, gotoLine, highlightSelectionMatches, openSearchPanel, replaceAll, replaceNext, search, searchKeymap, searchPanelOpen, selectMatches, selectNextOccurrence, selectSelectionMatches, setSearchQuery };
|
||||||
385
editor/node_modules/@codemirror/search/dist/index.d.ts
generated
vendored
Normal file
385
editor/node_modules/@codemirror/search/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
import * as _codemirror_state from '@codemirror/state';
|
||||||
|
import { Text, Extension, StateCommand, EditorState, SelectionRange, StateEffect } from '@codemirror/state';
|
||||||
|
import { Command, KeyBinding, EditorView, Panel } from '@codemirror/view';
|
||||||
|
|
||||||
|
/**
|
||||||
|
A search cursor provides an iterator over text matches in a
|
||||||
|
document.
|
||||||
|
*/
|
||||||
|
declare class SearchCursor implements Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
}> {
|
||||||
|
private test?;
|
||||||
|
private iter;
|
||||||
|
/**
|
||||||
|
The current match (only holds a meaningful value after
|
||||||
|
[`next`](https://codemirror.net/6/docs/ref/#search.SearchCursor.next) has been called and when
|
||||||
|
`done` is false).
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Whether the end of the iterated region has been reached.
|
||||||
|
*/
|
||||||
|
done: boolean;
|
||||||
|
private matches;
|
||||||
|
private buffer;
|
||||||
|
private bufferPos;
|
||||||
|
private bufferStart;
|
||||||
|
private normalize;
|
||||||
|
private query;
|
||||||
|
/**
|
||||||
|
Create a text cursor. The query is the search string, `from` to
|
||||||
|
`to` provides the region to search.
|
||||||
|
|
||||||
|
When `normalize` is given, it will be called, on both the query
|
||||||
|
string and the content it is matched against, before comparing.
|
||||||
|
You can, for example, create a case-insensitive search by
|
||||||
|
passing `s => s.toLowerCase()`.
|
||||||
|
|
||||||
|
Text is always normalized with
|
||||||
|
[`.normalize("NFKD")`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
||||||
|
(when supported).
|
||||||
|
*/
|
||||||
|
constructor(text: Text, query: string, from?: number, to?: number, normalize?: (string: string) => string, test?: ((from: number, to: number, buffer: string, bufferPos: number) => boolean) | undefined);
|
||||||
|
private peek;
|
||||||
|
/**
|
||||||
|
Look for the next match. Updates the iterator's
|
||||||
|
[`value`](https://codemirror.net/6/docs/ref/#search.SearchCursor.value) and
|
||||||
|
[`done`](https://codemirror.net/6/docs/ref/#search.SearchCursor.done) properties. Should be called
|
||||||
|
at least once before using the cursor.
|
||||||
|
*/
|
||||||
|
next(): this;
|
||||||
|
/**
|
||||||
|
The `next` method will ignore matches that partially overlap a
|
||||||
|
previous match. This method behaves like `next`, but includes
|
||||||
|
such matches.
|
||||||
|
*/
|
||||||
|
nextOverlapping(): this;
|
||||||
|
private match;
|
||||||
|
[Symbol.iterator]: () => Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RegExpCursorOptions {
|
||||||
|
ignoreCase?: boolean;
|
||||||
|
test?: (from: number, to: number, match: RegExpExecArray) => boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
This class is similar to [`SearchCursor`](https://codemirror.net/6/docs/ref/#search.SearchCursor)
|
||||||
|
but searches for a regular expression pattern instead of a plain
|
||||||
|
string.
|
||||||
|
*/
|
||||||
|
declare class RegExpCursor implements Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
match: RegExpExecArray;
|
||||||
|
}> {
|
||||||
|
private text;
|
||||||
|
private to;
|
||||||
|
private iter;
|
||||||
|
private re;
|
||||||
|
private test?;
|
||||||
|
private curLine;
|
||||||
|
private curLineStart;
|
||||||
|
private matchPos;
|
||||||
|
/**
|
||||||
|
Set to `true` when the cursor has reached the end of the search
|
||||||
|
range.
|
||||||
|
*/
|
||||||
|
done: boolean;
|
||||||
|
/**
|
||||||
|
Will contain an object with the extent of the match and the
|
||||||
|
match object when [`next`](https://codemirror.net/6/docs/ref/#search.RegExpCursor.next)
|
||||||
|
sucessfully finds a match.
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
match: RegExpExecArray;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Create a cursor that will search the given range in the given
|
||||||
|
document. `query` should be the raw pattern (as you'd pass it to
|
||||||
|
`new RegExp`).
|
||||||
|
*/
|
||||||
|
constructor(text: Text, query: string, options?: RegExpCursorOptions, from?: number, to?: number);
|
||||||
|
private getLine;
|
||||||
|
private nextLine;
|
||||||
|
/**
|
||||||
|
Move to the next match, if there is one.
|
||||||
|
*/
|
||||||
|
next(): this;
|
||||||
|
[Symbol.iterator]: () => Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
match: RegExpExecArray;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Command that shows a dialog asking the user for a line number, and
|
||||||
|
when a valid position is provided, moves the cursor to that line.
|
||||||
|
|
||||||
|
Supports line numbers, relative line offsets prefixed with `+` or
|
||||||
|
`-`, document percentages suffixed with `%`, and an optional
|
||||||
|
column position by adding `:` and a second number after the line
|
||||||
|
number.
|
||||||
|
*/
|
||||||
|
declare const gotoLine: Command;
|
||||||
|
|
||||||
|
type HighlightOptions = {
|
||||||
|
/**
|
||||||
|
Determines whether, when nothing is selected, the word around
|
||||||
|
the cursor is matched instead. Defaults to false.
|
||||||
|
*/
|
||||||
|
highlightWordAroundCursor?: boolean;
|
||||||
|
/**
|
||||||
|
The minimum length of the selection before it is highlighted.
|
||||||
|
Defaults to 1 (always highlight non-cursor selections).
|
||||||
|
*/
|
||||||
|
minSelectionLength?: number;
|
||||||
|
/**
|
||||||
|
The amount of matches (in the viewport) at which to disable
|
||||||
|
highlighting. Defaults to 100.
|
||||||
|
*/
|
||||||
|
maxMatches?: number;
|
||||||
|
/**
|
||||||
|
Whether to only highlight whole words.
|
||||||
|
*/
|
||||||
|
wholeWords?: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
This extension highlights text that matches the selection. It uses
|
||||||
|
the `"cm-selectionMatch"` class for the highlighting. When
|
||||||
|
`highlightWordAroundCursor` is enabled, the word at the cursor
|
||||||
|
itself will be highlighted with `"cm-selectionMatch-main"`.
|
||||||
|
*/
|
||||||
|
declare function highlightSelectionMatches(options?: HighlightOptions): Extension;
|
||||||
|
/**
|
||||||
|
Select next occurrence of the current selection. Expand selection
|
||||||
|
to the surrounding word when the selection is empty.
|
||||||
|
*/
|
||||||
|
declare const selectNextOccurrence: StateCommand;
|
||||||
|
|
||||||
|
interface SearchConfig {
|
||||||
|
/**
|
||||||
|
Whether to position the search panel at the top of the editor
|
||||||
|
(the default is at the bottom).
|
||||||
|
*/
|
||||||
|
top?: boolean;
|
||||||
|
/**
|
||||||
|
Whether to enable case sensitivity by default when the search
|
||||||
|
panel is activated (defaults to false).
|
||||||
|
*/
|
||||||
|
caseSensitive?: boolean;
|
||||||
|
/**
|
||||||
|
Whether to treat string searches literally by default (defaults to false).
|
||||||
|
*/
|
||||||
|
literal?: boolean;
|
||||||
|
/**
|
||||||
|
Controls whether the default query has by-word matching enabled.
|
||||||
|
Defaults to false.
|
||||||
|
*/
|
||||||
|
wholeWord?: boolean;
|
||||||
|
/**
|
||||||
|
Used to turn on regular expression search in the default query.
|
||||||
|
Defaults to false.
|
||||||
|
*/
|
||||||
|
regexp?: boolean;
|
||||||
|
/**
|
||||||
|
Can be used to override the way the search panel is implemented.
|
||||||
|
Should create a [Panel](https://codemirror.net/6/docs/ref/#view.Panel) that contains a form
|
||||||
|
which lets the user:
|
||||||
|
|
||||||
|
- See the [current](https://codemirror.net/6/docs/ref/#search.getSearchQuery) search query.
|
||||||
|
- Manipulate the [query](https://codemirror.net/6/docs/ref/#search.SearchQuery) and
|
||||||
|
[update](https://codemirror.net/6/docs/ref/#search.setSearchQuery) the search state with a new
|
||||||
|
query.
|
||||||
|
- Notice external changes to the query by reacting to the
|
||||||
|
appropriate [state effect](https://codemirror.net/6/docs/ref/#search.setSearchQuery).
|
||||||
|
- Run some of the search commands.
|
||||||
|
|
||||||
|
The field that should be focused when opening the panel must be
|
||||||
|
tagged with a `main-field=true` DOM attribute.
|
||||||
|
*/
|
||||||
|
createPanel?: (view: EditorView) => Panel;
|
||||||
|
/**
|
||||||
|
By default, matches are scrolled into view using the default
|
||||||
|
behavior of
|
||||||
|
[`EditorView.scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView).
|
||||||
|
This option allows you to pass a custom function to produce the
|
||||||
|
scroll effect.
|
||||||
|
*/
|
||||||
|
scrollToMatch?: (range: SelectionRange, view: EditorView) => StateEffect<unknown>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Add search state to the editor configuration, and optionally
|
||||||
|
configure the search extension.
|
||||||
|
([`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) will automatically
|
||||||
|
enable this if it isn't already on).
|
||||||
|
*/
|
||||||
|
declare function search(config?: SearchConfig): Extension;
|
||||||
|
/**
|
||||||
|
A search query. Part of the editor's search state.
|
||||||
|
*/
|
||||||
|
declare class SearchQuery {
|
||||||
|
/**
|
||||||
|
The search string (or regular expression).
|
||||||
|
*/
|
||||||
|
readonly search: string;
|
||||||
|
/**
|
||||||
|
Indicates whether the search is case-sensitive.
|
||||||
|
*/
|
||||||
|
readonly caseSensitive: boolean;
|
||||||
|
/**
|
||||||
|
By default, string search will replace `\n`, `\r`, and `\t` in
|
||||||
|
the query with newline, return, and tab characters. When this
|
||||||
|
is set to true, that behavior is disabled.
|
||||||
|
*/
|
||||||
|
readonly literal: boolean;
|
||||||
|
/**
|
||||||
|
When true, the search string is interpreted as a regular
|
||||||
|
expression.
|
||||||
|
*/
|
||||||
|
readonly regexp: boolean;
|
||||||
|
/**
|
||||||
|
The replace text, or the empty string if no replace text has
|
||||||
|
been given.
|
||||||
|
*/
|
||||||
|
readonly replace: string;
|
||||||
|
/**
|
||||||
|
Whether this query is non-empty and, in case of a regular
|
||||||
|
expression search, syntactically valid.
|
||||||
|
*/
|
||||||
|
readonly valid: boolean;
|
||||||
|
/**
|
||||||
|
When true, matches that contain words are ignored when there are
|
||||||
|
further word characters around them.
|
||||||
|
*/
|
||||||
|
readonly wholeWord: boolean;
|
||||||
|
/**
|
||||||
|
Optional test function used to filter matches.
|
||||||
|
*/
|
||||||
|
readonly test: ((match: string, state: EditorState, from: number, to: number) => boolean) | undefined;
|
||||||
|
/**
|
||||||
|
Create a query object.
|
||||||
|
*/
|
||||||
|
constructor(config: {
|
||||||
|
/**
|
||||||
|
The search string.
|
||||||
|
*/
|
||||||
|
search: string;
|
||||||
|
/**
|
||||||
|
Controls whether the search should be case-sensitive.
|
||||||
|
*/
|
||||||
|
caseSensitive?: boolean;
|
||||||
|
/**
|
||||||
|
By default, string search will replace `\n`, `\r`, and `\t` in
|
||||||
|
the query with newline, return, and tab characters. When this
|
||||||
|
is set to true, that behavior is disabled.
|
||||||
|
*/
|
||||||
|
literal?: boolean;
|
||||||
|
/**
|
||||||
|
When true, interpret the search string as a regular expression.
|
||||||
|
*/
|
||||||
|
regexp?: boolean;
|
||||||
|
/**
|
||||||
|
The replace text.
|
||||||
|
*/
|
||||||
|
replace?: string;
|
||||||
|
/**
|
||||||
|
Enable whole-word matching.
|
||||||
|
*/
|
||||||
|
wholeWord?: boolean;
|
||||||
|
/**
|
||||||
|
Optional custom filter. It is passed the matched string, the
|
||||||
|
editor state, and the match range. Matches for which it
|
||||||
|
returns false will be ignored.
|
||||||
|
*/
|
||||||
|
test?: (match: string, state: EditorState, from: number, to: number) => boolean;
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
Compare this query to another query.
|
||||||
|
*/
|
||||||
|
eq(other: SearchQuery): boolean;
|
||||||
|
/**
|
||||||
|
Get a search cursor for this query, searching through the given
|
||||||
|
range in the given state.
|
||||||
|
*/
|
||||||
|
getCursor(state: EditorState | Text, from?: number, to?: number): Iterator<{
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
A state effect that updates the current search query. Note that
|
||||||
|
this only has an effect if the search state has been initialized
|
||||||
|
(by including [`search`](https://codemirror.net/6/docs/ref/#search.search) in your configuration or
|
||||||
|
by running [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) at least
|
||||||
|
once).
|
||||||
|
*/
|
||||||
|
declare const setSearchQuery: _codemirror_state.StateEffectType<SearchQuery>;
|
||||||
|
/**
|
||||||
|
Get the current search query from an editor state.
|
||||||
|
*/
|
||||||
|
declare function getSearchQuery(state: EditorState): SearchQuery;
|
||||||
|
/**
|
||||||
|
Query whether the search panel is open in the given editor state.
|
||||||
|
*/
|
||||||
|
declare function searchPanelOpen(state: EditorState): boolean;
|
||||||
|
/**
|
||||||
|
Open the search panel if it isn't already open, and move the
|
||||||
|
selection to the first match after the current main selection.
|
||||||
|
Will wrap around to the start of the document when it reaches the
|
||||||
|
end.
|
||||||
|
*/
|
||||||
|
declare const findNext: Command;
|
||||||
|
/**
|
||||||
|
Move the selection to the previous instance of the search query,
|
||||||
|
before the current main selection. Will wrap past the start
|
||||||
|
of the document to start searching at the end again.
|
||||||
|
*/
|
||||||
|
declare const findPrevious: Command;
|
||||||
|
/**
|
||||||
|
Select all instances of the search query.
|
||||||
|
*/
|
||||||
|
declare const selectMatches: Command;
|
||||||
|
/**
|
||||||
|
Select all instances of the currently selected text.
|
||||||
|
*/
|
||||||
|
declare const selectSelectionMatches: StateCommand;
|
||||||
|
/**
|
||||||
|
Replace the current match of the search query.
|
||||||
|
*/
|
||||||
|
declare const replaceNext: Command;
|
||||||
|
/**
|
||||||
|
Replace all instances of the search query with the given
|
||||||
|
replacement.
|
||||||
|
*/
|
||||||
|
declare const replaceAll: Command;
|
||||||
|
/**
|
||||||
|
Make sure the search panel is open and focused.
|
||||||
|
*/
|
||||||
|
declare const openSearchPanel: Command;
|
||||||
|
/**
|
||||||
|
Close the search panel.
|
||||||
|
*/
|
||||||
|
declare const closeSearchPanel: Command;
|
||||||
|
/**
|
||||||
|
Default search-related key bindings.
|
||||||
|
|
||||||
|
- Mod-f: [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel)
|
||||||
|
- F3, Mod-g: [`findNext`](https://codemirror.net/6/docs/ref/#search.findNext)
|
||||||
|
- Shift-F3, Shift-Mod-g: [`findPrevious`](https://codemirror.net/6/docs/ref/#search.findPrevious)
|
||||||
|
- Mod-Alt-g: [`gotoLine`](https://codemirror.net/6/docs/ref/#search.gotoLine)
|
||||||
|
- Mod-d: [`selectNextOccurrence`](https://codemirror.net/6/docs/ref/#search.selectNextOccurrence)
|
||||||
|
*/
|
||||||
|
declare const searchKeymap: readonly KeyBinding[];
|
||||||
|
|
||||||
|
export { RegExpCursor, SearchCursor, SearchQuery, closeSearchPanel, findNext, findPrevious, getSearchQuery, gotoLine, highlightSelectionMatches, openSearchPanel, replaceAll, replaceNext, search, searchKeymap, searchPanelOpen, selectMatches, selectNextOccurrence, selectSelectionMatches, setSearchQuery };
|
||||||
1217
editor/node_modules/@codemirror/search/dist/index.js
generated
vendored
Normal file
1217
editor/node_modules/@codemirror/search/dist/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
40
editor/node_modules/@codemirror/search/package.json
generated
vendored
Normal file
40
editor/node_modules/@codemirror/search/package.json
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "@codemirror/search",
|
||||||
|
"version": "6.6.0",
|
||||||
|
"description": "Search functionality for the CodeMirror code editor",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cm-runtests",
|
||||||
|
"prepare": "cm-buildhelper src/search.ts"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"code"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Marijn Haverbeke",
|
||||||
|
"email": "marijn@haverbeke.berlin",
|
||||||
|
"url": "http://marijnhaverbeke.nl"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"sideEffects": false,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.37.0",
|
||||||
|
"crelt": "^1.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/buildhelper": "^1.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/codemirror/search.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
16
editor/node_modules/@codemirror/state/.github/workflows/dispatch.yml
generated
vendored
Normal file
16
editor/node_modules/@codemirror/state/.github/workflows/dispatch.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Trigger CI
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Dispatch to main repo
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Emit repository_dispatch
|
||||||
|
uses: mvasigh/dispatch-action@main
|
||||||
|
with:
|
||||||
|
# You should create a personal access token and store it in your repository
|
||||||
|
token: ${{ secrets.DISPATCH_AUTH }}
|
||||||
|
repo: dev
|
||||||
|
owner: codemirror
|
||||||
|
event_type: push
|
||||||
308
editor/node_modules/@codemirror/state/CHANGELOG.md
generated
vendored
Normal file
308
editor/node_modules/@codemirror/state/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
## 6.6.0 (2026-03-12)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`EditorSelection.range` now takes an optional `assoc` argument.
|
||||||
|
|
||||||
|
`SelectionRange.extend` can now be given a third argument to specify associativity.
|
||||||
|
|
||||||
|
## 6.5.4 (2026-01-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make `SelectionRange.eq` return false when the ranges have different goal columns.
|
||||||
|
|
||||||
|
## 6.5.3 (2025-12-22)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where `RangeValue.eq` could get called with a value of a different class.
|
||||||
|
|
||||||
|
`EditorState.charCategorizer` now only uses the highest-precedence set of word characters from the language data, to allow overriding these.
|
||||||
|
|
||||||
|
## 6.5.2 (2025-02-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where reconfiguring a field with a new `init` value didn't update the value of the field.
|
||||||
|
|
||||||
|
## 6.5.1 (2025-01-10)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
`countColumn` no longer loops infinitely when given a `to` that's higher than the input string's length.
|
||||||
|
|
||||||
|
## 6.5.0 (2024-12-09)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`RangeSet.compare` now supports a `boundChange` callback that is called when there's a change in the way ranges are split.
|
||||||
|
|
||||||
|
## 6.4.1 (2024-02-19)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue that caused widgets at the end of a mark decoration to be rendered in their own separate mark DOM element.
|
||||||
|
|
||||||
|
## 6.4.0 (2023-12-28)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
When multiple ranges in a single range set overlap, put the smaller ones inside the bigger ones, so that overlapping decorations don't break up each other's elements when coming from the same source.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
Selection and selection range `eq` methods now support an optional argument that makes them also compare by cursor associativity.
|
||||||
|
|
||||||
|
The `RangeSet.join` function can be used to join multiple range sets together.
|
||||||
|
|
||||||
|
## 6.3.3 (2023-12-06)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where `Text.slice` and `Text.replace` could return objects with incorrect `length` when the given `from`/`to` values were out of range for the text.
|
||||||
|
|
||||||
|
## 6.3.2 (2023-11-27)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Make sure transactions cannot add multiple selections when `allowMultipleSelections` is false.
|
||||||
|
|
||||||
|
Fix a bug that caused `Text.iterLines` to not return empty lines at the end of the iterated ranges.
|
||||||
|
|
||||||
|
## 6.3.1 (2023-10-18)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Give the tag property on `FacetReader` the type of the output type parameter to force TypeScript to infer the proper type when converting from `Facet` to `FacetReader`.
|
||||||
|
|
||||||
|
## 6.3.0 (2023-10-12)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `FacetReader` type provides a way to export a read-only handle to a `Facet`.
|
||||||
|
|
||||||
|
## 6.2.1 (2023-05-23)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue that could cause `RangeSet.compare` to miss changes in the set of active ranges around a point range.
|
||||||
|
|
||||||
|
## 6.2.0 (2022-12-26)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`EditorSelection.range` now accepts an optional 4th argument to specify the bidi level of the range's head position.
|
||||||
|
|
||||||
|
## 6.1.4 (2022-11-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused the `openStart` value passed to span iterators to be incorrect around widgets in some circumstances.
|
||||||
|
|
||||||
|
## 6.1.3 (2022-11-10)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Avoid unnecessary calls to computed facet getters when a state is reconfigured but no dependencies of the computed facet change.
|
||||||
|
|
||||||
|
Fix an infinite loop in `RangeSet.eq` when the `to` parameter isn't given.
|
||||||
|
|
||||||
|
## 6.1.2 (2022-09-21)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where, when multiple transaction extenders took effect, only the highest-precedence one was actually included in the transaction.
|
||||||
|
|
||||||
|
## 6.1.1 (2022-08-03)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug in range set span iteration that would cause decorations to be inappropriately split in some situations.
|
||||||
|
|
||||||
|
## 6.1.0 (2022-06-30)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Refine change mapping to preserve insertions made by concurrent changes.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `enables` option to `Facet.define` may now take a function, which will be called with the facet value to create the extensions.
|
||||||
|
|
||||||
|
## 6.0.1 (2022-06-17)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a problem that caused effects' `map` methods to be called with an incorrect change set when filtering changes.
|
||||||
|
|
||||||
|
## 6.0.0 (2022-06-08)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
Update dependencies to 6.0.0
|
||||||
|
|
||||||
|
## 0.20.1 (2022-06-02)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`EditorView.phrase` now accepts additional arguments, which it will interpolate into the phrase in the place of `$` markers.
|
||||||
|
|
||||||
|
## 0.20.0 (2022-04-20)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
The deprecated precedence names `fallback`, `extend`, and `override` were removed from the library.
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where, if an extension value occurs multiple times, its lowest, rather than highest precedence is used.
|
||||||
|
|
||||||
|
Fix an issue where facets with computed inputs would unneccesarily have their outputs recreated on state reconfiguration.
|
||||||
|
|
||||||
|
Fix a bug in the order in which new values for state fields and facets were computed, which could cause dynamic facets to hold the wrong value in some situations.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The exports from @codemirror/rangeset now live in this package.
|
||||||
|
|
||||||
|
The exports from @codemirror/text now live in this package.
|
||||||
|
|
||||||
|
## 0.19.9 (2022-02-16)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Mapping a non-empty selection range now always puts any newly inserted text on the sides of the range outside of the mapped version.
|
||||||
|
|
||||||
|
## 0.19.8 (2022-02-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where facet values with computed inputs could incorrectly retain their old value on reconfiguration.
|
||||||
|
|
||||||
|
## 0.19.7 (2022-02-11)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Avoid recomputing facets on state reconfiguration if that facet's inputs stayed precisely the same.
|
||||||
|
|
||||||
|
Selection ranges created with `EditorSelection.range` will now have an assoc pointing at their anchor, when non-empty.
|
||||||
|
|
||||||
|
## 0.19.6 (2021-11-19)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that caused facet compare functions to be called with an invalid value in some situations.
|
||||||
|
|
||||||
|
Fix a bug that caused dynamic facet values to be incorrectly kept unchanged when reconfiguration changed one of their dependencies.
|
||||||
|
|
||||||
|
## 0.19.5 (2021-11-10)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug that would cause dynamic facet values influenced by a state reconfiguration to not properly recompute.
|
||||||
|
|
||||||
|
## 0.19.4 (2021-11-05)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
When reconfiguring a state, effects from the reconfiguring transaction can now be seen by newly added state fields.
|
||||||
|
|
||||||
|
## 0.19.3 (2021-11-03)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The precedence levels (under `Prec`) now have more generic names, because their 'meaningful' names were entirely inappropriate in many situations.
|
||||||
|
|
||||||
|
## 0.19.2 (2021-09-13)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The editor state now has a `readOnly` property with a matching facet to control its value.
|
||||||
|
|
||||||
|
## 0.19.1 (2021-08-15)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix a bug where `wordAt` never returned a useful result.
|
||||||
|
|
||||||
|
## 0.19.0 (2021-08-11)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
User event strings now work differently—the events emitted by the core packages follow a different system, and hierarchical event tags can be created by separating the words with dots.
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`languageDataAt` now takes an optional `side` argument to specificy which side of the position you're interested in.
|
||||||
|
|
||||||
|
It is now possible to add a user event annotation with a direct `userEvent` property on a transaction spec.
|
||||||
|
|
||||||
|
Transactions now have an `isUserEvent` method that can be used to check if it is (a subtype of) some user event type.
|
||||||
|
|
||||||
|
## 0.18.7 (2021-05-04)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue where state fields might be initialized with a state that they aren't actually part of during reconfiguration.
|
||||||
|
|
||||||
|
## 0.18.6 (2021-04-12)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `EditorState.wordAt` method finds the word at a given position.
|
||||||
|
|
||||||
|
## 0.18.5 (2021-04-08)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix an issue in the compiled output that would break the code when minified with terser.
|
||||||
|
|
||||||
|
## 0.18.4 (2021-04-06)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `Transaction.remote` annotation can be used to mark and recognize transactions created by other actors.
|
||||||
|
|
||||||
|
## 0.18.3 (2021-03-23)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The `ChangeDesc` class now has `toJSON` and `fromJSON` methods.
|
||||||
|
|
||||||
|
## 0.18.2 (2021-03-14)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
Fix unintended ES2020 output (the package contains ES6 code again).
|
||||||
|
|
||||||
|
## 0.18.1 (2021-03-10)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The new `Compartment.get` method can be used to get the content of a compartment in a given state.
|
||||||
|
|
||||||
|
## 0.18.0 (2021-03-03)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
`tagExtension` and the `reconfigure` transaction spec property have been replaced with the concept of configuration compartments and reconfiguration effects (see `Compartment`, `StateEffect.reconfigure`, and `StateEffect.appendConfig`).
|
||||||
|
|
||||||
|
## 0.17.2 (2021-02-19)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
`EditorSelection.map` and `SelectionRange.map` now take an optional second argument to indicate which direction to map to.
|
||||||
|
|
||||||
|
## 0.17.1 (2021-01-06)
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
The package now also exports a CommonJS module.
|
||||||
|
|
||||||
|
## 0.17.0 (2020-12-29)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
First numbered release.
|
||||||
|
|
||||||
21
editor/node_modules/@codemirror/state/LICENSE
generated
vendored
Normal file
21
editor/node_modules/@codemirror/state/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
18
editor/node_modules/@codemirror/state/README.md
generated
vendored
Normal file
18
editor/node_modules/@codemirror/state/README.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# @codemirror/state [](https://www.npmjs.org/package/@codemirror/state)
|
||||||
|
|
||||||
|
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#state) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/state/blob/main/CHANGELOG.md) ]
|
||||||
|
|
||||||
|
This package implements the editor state data structures for the
|
||||||
|
[CodeMirror](https://codemirror.net/) code editor.
|
||||||
|
|
||||||
|
The [project page](https://codemirror.net/) has more information, a
|
||||||
|
number of [examples](https://codemirror.net/examples/) and the
|
||||||
|
[documentation](https://codemirror.net/docs/).
|
||||||
|
|
||||||
|
This code is released under an
|
||||||
|
[MIT license](https://github.com/codemirror/state/tree/main/LICENSE).
|
||||||
|
|
||||||
|
We aim to be an inclusive, welcoming community. To make that explicit,
|
||||||
|
we have a [code of
|
||||||
|
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
||||||
|
to communication around the project.
|
||||||
3922
editor/node_modules/@codemirror/state/dist/index.cjs
generated
vendored
Normal file
3922
editor/node_modules/@codemirror/state/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1713
editor/node_modules/@codemirror/state/dist/index.d.cts
generated
vendored
Normal file
1713
editor/node_modules/@codemirror/state/dist/index.d.cts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1713
editor/node_modules/@codemirror/state/dist/index.d.ts
generated
vendored
Normal file
1713
editor/node_modules/@codemirror/state/dist/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3892
editor/node_modules/@codemirror/state/dist/index.js
generated
vendored
Normal file
3892
editor/node_modules/@codemirror/state/dist/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
38
editor/node_modules/@codemirror/state/package.json
generated
vendored
Normal file
38
editor/node_modules/@codemirror/state/package.json
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "@codemirror/state",
|
||||||
|
"version": "6.6.0",
|
||||||
|
"description": "Editor state data structures for the CodeMirror code editor",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cm-runtests",
|
||||||
|
"prepare": "cm-buildhelper src/index.ts"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"code"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Marijn Haverbeke",
|
||||||
|
"email": "marijn@haverbeke.berlin",
|
||||||
|
"url": "http://marijnhaverbeke.nl"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"sideEffects": false,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@marijn/find-cluster-break": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/buildhelper": "^1.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/codemirror/state.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
16
editor/node_modules/@codemirror/view/.github/workflows/dispatch.yml
generated
vendored
Normal file
16
editor/node_modules/@codemirror/view/.github/workflows/dispatch.yml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: Trigger CI
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Dispatch to main repo
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Emit repository_dispatch
|
||||||
|
uses: mvasigh/dispatch-action@main
|
||||||
|
with:
|
||||||
|
# You should create a personal access token and store it in your repository
|
||||||
|
token: ${{ secrets.DISPATCH_AUTH }}
|
||||||
|
repo: dev
|
||||||
|
owner: codemirror
|
||||||
|
event_type: push
|
||||||
2284
editor/node_modules/@codemirror/view/CHANGELOG.md
generated
vendored
Normal file
2284
editor/node_modules/@codemirror/view/CHANGELOG.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
editor/node_modules/@codemirror/view/LICENSE
generated
vendored
Normal file
21
editor/node_modules/@codemirror/view/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
37
editor/node_modules/@codemirror/view/README.md
generated
vendored
Normal file
37
editor/node_modules/@codemirror/view/README.md
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# @codemirror/view [](https://www.npmjs.org/package/@codemirror/view)
|
||||||
|
|
||||||
|
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#view) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/) | [**CHANGELOG**](https://github.com/codemirror/view/blob/main/CHANGELOG.md) ]
|
||||||
|
|
||||||
|
This package implements the DOM view component for the
|
||||||
|
[CodeMirror](https://codemirror.net/) code editor.
|
||||||
|
|
||||||
|
The [project page](https://codemirror.net/) has more information, a
|
||||||
|
number of [examples](https://codemirror.net/examples/) and the
|
||||||
|
[documentation](https://codemirror.net/docs/).
|
||||||
|
|
||||||
|
This code is released under an
|
||||||
|
[MIT license](https://github.com/codemirror/view/tree/main/LICENSE).
|
||||||
|
|
||||||
|
We aim to be an inclusive, welcoming community. To make that explicit,
|
||||||
|
we have a [code of
|
||||||
|
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
||||||
|
to communication around the project.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {EditorView} from "@codemirror/view"
|
||||||
|
import {basicSetup} from "codemirror"
|
||||||
|
|
||||||
|
const view = new EditorView({
|
||||||
|
parent: document.querySelector("#some-node"),
|
||||||
|
doc: "Content text",
|
||||||
|
extensions: [basicSetup /* ... */]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Add additional extensions, such as a [language
|
||||||
|
mode](https://codemirror.net/#languages), to configure the editor.
|
||||||
|
Call
|
||||||
|
[`view.dispatch`](https://codemirror.net/docs/ref/#view.EditorView.dispatch)
|
||||||
|
to update the editor's state.
|
||||||
11796
editor/node_modules/@codemirror/view/dist/index.cjs
generated
vendored
Normal file
11796
editor/node_modules/@codemirror/view/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2389
editor/node_modules/@codemirror/view/dist/index.d.cts
generated
vendored
Normal file
2389
editor/node_modules/@codemirror/view/dist/index.d.cts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2389
editor/node_modules/@codemirror/view/dist/index.d.ts
generated
vendored
Normal file
2389
editor/node_modules/@codemirror/view/dist/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11745
editor/node_modules/@codemirror/view/dist/index.js
generated
vendored
Normal file
11745
editor/node_modules/@codemirror/view/dist/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
41
editor/node_modules/@codemirror/view/package.json
generated
vendored
Normal file
41
editor/node_modules/@codemirror/view/package.json
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "@codemirror/view",
|
||||||
|
"version": "6.41.0",
|
||||||
|
"description": "DOM view component for the CodeMirror code editor",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cm-runtests",
|
||||||
|
"prepare": "cm-buildhelper src/index.ts"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"editor",
|
||||||
|
"code"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Marijn Haverbeke",
|
||||||
|
"email": "marijn@haverbeke.berlin",
|
||||||
|
"url": "http://marijnhaverbeke.nl"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"sideEffects": false,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/state": "^6.6.0",
|
||||||
|
"crelt": "^1.0.6",
|
||||||
|
"style-mod": "^4.1.0",
|
||||||
|
"w3c-keyname": "^2.2.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@codemirror/buildhelper": "^1.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/codemirror/view.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
editor/node_modules/@esbuild/darwin-arm64/README.md
generated
vendored
Normal file
3
editor/node_modules/@esbuild/darwin-arm64/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# esbuild
|
||||||
|
|
||||||
|
This is the macOS ARM 64-bit binary for esbuild, a JavaScript bundler and minifier. See https://github.com/evanw/esbuild for details.
|
||||||
BIN
editor/node_modules/@esbuild/darwin-arm64/bin/esbuild
generated
vendored
Executable file
BIN
editor/node_modules/@esbuild/darwin-arm64/bin/esbuild
generated
vendored
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user