yerba 0.4.2-aarch64-linux-gnu → 0.5.1-aarch64-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +242 -54
  3. data/exe/aarch64-linux-gnu/yerba +0 -0
  4. data/ext/yerba/include/yerba.h +13 -1
  5. data/ext/yerba/yerba.c +239 -113
  6. data/lib/yerba/3.2/yerba.so +0 -0
  7. data/lib/yerba/3.3/yerba.so +0 -0
  8. data/lib/yerba/3.4/yerba.so +0 -0
  9. data/lib/yerba/4.0/yerba.so +0 -0
  10. data/lib/yerba/document.rb +54 -18
  11. data/lib/yerba/map.rb +55 -43
  12. data/lib/yerba/node.rb +58 -0
  13. data/lib/yerba/scalar.rb +20 -23
  14. data/lib/yerba/sequence.rb +88 -55
  15. data/lib/yerba/version.rb +1 -1
  16. data/lib/yerba.rb +2 -0
  17. data/rust/Cargo.lock +1120 -35
  18. data/rust/Cargo.toml +3 -2
  19. data/rust/src/commands/delete.rs +1 -1
  20. data/rust/src/commands/get.rs +47 -12
  21. data/rust/src/commands/insert.rs +1 -1
  22. data/rust/src/commands/location.rs +56 -0
  23. data/rust/src/commands/mod.rs +33 -5
  24. data/rust/src/commands/remove.rs +1 -1
  25. data/rust/src/commands/rename.rs +1 -1
  26. data/rust/src/commands/schema.rs +84 -0
  27. data/rust/src/commands/selectors.rs +4 -4
  28. data/rust/src/commands/set.rs +1 -1
  29. data/rust/src/commands/sort.rs +1 -1
  30. data/rust/src/commands/unique.rs +80 -0
  31. data/rust/src/document/condition.rs +18 -2
  32. data/rust/src/document/delete.rs +52 -8
  33. data/rust/src/document/get.rs +256 -25
  34. data/rust/src/document/insert.rs +3 -3
  35. data/rust/src/document/mod.rs +112 -34
  36. data/rust/src/document/schema.rs +73 -0
  37. data/rust/src/document/set.rs +1 -1
  38. data/rust/src/document/sort.rs +21 -15
  39. data/rust/src/document/style.rs +3 -3
  40. data/rust/src/document/unique.rs +86 -0
  41. data/rust/src/error.rs +78 -0
  42. data/rust/src/ffi.rs +89 -9
  43. data/rust/src/json.rs +16 -16
  44. data/rust/src/lib.rs +7 -12
  45. data/rust/src/main.rs +2 -0
  46. data/rust/src/schema.rs +93 -0
  47. data/rust/src/selector.rs +16 -0
  48. data/rust/src/syntax.rs +91 -31
  49. data/rust/src/yerbafile.rs +127 -81
  50. metadata +9 -2
@@ -1,6 +1,37 @@
1
1
  use super::*;
2
2
 
3
3
  impl Document {
4
+ pub fn is_valid_selector(&self, dot_path: &str) -> bool {
5
+ if dot_path.is_empty() {
6
+ return true;
7
+ }
8
+
9
+ let selectors = self.selectors();
10
+
11
+ if selectors.contains(&dot_path.to_string()) {
12
+ return true;
13
+ }
14
+
15
+ let wildcard_version = dot_path.replace(|c: char| c.is_ascii_digit(), "").replace("[.", "[");
16
+
17
+ let mut normalized = String::new();
18
+ let mut chars = dot_path.chars().peekable();
19
+
20
+ while let Some(char) = chars.next() {
21
+ if char == '[' {
22
+ normalized.push('[');
23
+
24
+ while chars.peek().map(|char| char.is_ascii_digit()).unwrap_or(false) {
25
+ chars.next();
26
+ }
27
+ } else {
28
+ normalized.push(char);
29
+ }
30
+ }
31
+
32
+ selectors.contains(&normalized) || selectors.contains(&wildcard_version)
33
+ }
34
+
4
35
  pub fn get(&self, dot_path: &str) -> Option<String> {
5
36
  if dot_path.contains('[') {
6
37
  return self.get_all(dot_path).into_iter().next();
@@ -12,7 +43,7 @@ impl Document {
12
43
  }
13
44
 
14
45
  pub fn get_all(&self, dot_path: &str) -> Vec<String> {
15
- self.navigate_all(dot_path).iter().filter_map(extract_scalar_text).collect()
46
+ self.navigate_all_compact(dot_path).iter().filter_map(extract_scalar_text).collect()
16
47
  }
17
48
 
18
49
  pub fn get_typed(&self, dot_path: &str) -> Option<ScalarValue> {
@@ -34,7 +65,7 @@ impl Document {
34
65
 
35
66
  pub fn get_all_typed(&self, dot_path: &str) -> Vec<ScalarValue> {
36
67
  self
37
- .navigate_all(dot_path)
68
+ .navigate_all_compact(dot_path)
38
69
  .iter()
39
70
  .filter(|node| {
40
71
  !node
@@ -45,6 +76,59 @@ impl Document {
45
76
  .collect()
46
77
  }
47
78
 
79
+ pub fn resolve_selectors(&self, dot_path: &str) -> Vec<String> {
80
+ self.navigate_all_compact(dot_path).iter().map(node_selector).collect()
81
+ }
82
+
83
+ pub fn get_all_located(&self, dot_path: &str) -> Vec<LocatedNode> {
84
+ let source = self.root.text().to_string();
85
+ let file_path = self.path.as_ref().map(|p| p.to_string_lossy().to_string());
86
+
87
+ self
88
+ .navigate_all_compact(dot_path)
89
+ .iter()
90
+ .map(|node| {
91
+ let offset: usize = node.text_range().start().into();
92
+ let line = source[..offset].matches('\n').count() + 1;
93
+ let selector = node_selector(node);
94
+ let is_scalar = !node
95
+ .descendants()
96
+ .any(|child| child.kind() == SyntaxKind::BLOCK_MAP || child.kind() == SyntaxKind::BLOCK_SEQ);
97
+
98
+ let (text, value_type) = if is_scalar {
99
+ extract_scalar(node)
100
+ .map(|s| (Some(s.text.clone()), Some(crate::syntax::detect_yaml_type(&s))))
101
+ .unwrap_or((None, None))
102
+ } else {
103
+ (None, None)
104
+ };
105
+
106
+ let node_type = if is_scalar {
107
+ "scalar"
108
+ } else {
109
+ let map_pos = node.descendants().find_map(BlockMap::cast).map(|m| m.syntax().text_range().start());
110
+ let seq_pos = node.descendants().find_map(BlockSeq::cast).map(|s| s.syntax().text_range().start());
111
+
112
+ match (map_pos, seq_pos) {
113
+ (Some(m), Some(s)) if s < m => "sequence",
114
+ (Some(_), _) => "map",
115
+ (None, Some(_)) => "sequence",
116
+ _ => "map",
117
+ }
118
+ };
119
+
120
+ LocatedNode {
121
+ node_type: node_type.to_string(),
122
+ text,
123
+ value_type,
124
+ file_path: file_path.clone(),
125
+ selector,
126
+ line,
127
+ }
128
+ })
129
+ .collect()
130
+ }
131
+
48
132
  pub fn node_type(&self, dot_path: &str) -> NodeType {
49
133
  match self.navigate(dot_path) {
50
134
  Ok(node) => {
@@ -97,15 +181,43 @@ impl Document {
97
181
  key_name,
98
182
  key_location,
99
183
  },
100
- None => NodeInfo {
101
- node_type: self.node_type(dot_path),
102
- is_list: false,
103
- value: None,
104
- list_values: vec![],
105
- location,
106
- key_name,
107
- key_location,
108
- },
184
+ None => {
185
+ let (node_type, entry_location, entry_key_name, entry_key_location) = if self.navigate(dot_path).is_err() {
186
+ if let Some(entry_node) = self.find_entry(dot_path) {
187
+ let range = entry_node.text_range();
188
+ let entry_location = compute_location(&source, range.start().into(), range.end().into());
189
+
190
+ let (node, location) = yaml_parser::ast::BlockMapEntry::cast(entry_node.clone())
191
+ .and_then(|entry| {
192
+ entry.key().and_then(|key_node| {
193
+ let key_text = extract_scalar_text(key_node.syntax())?;
194
+ let key_range = key_node.syntax().text_range();
195
+ let key_location = compute_location(&source, key_range.start().into(), key_range.end().into());
196
+
197
+ Some((key_text, key_location))
198
+ })
199
+ })
200
+ .map(|(name, location)| (Some(name), location))
201
+ .unwrap_or((None, Location::default()));
202
+
203
+ (NodeType::Scalar, entry_location, node, location)
204
+ } else {
205
+ (self.node_type(dot_path), location, key_name, key_location)
206
+ }
207
+ } else {
208
+ (self.node_type(dot_path), location, key_name, key_location)
209
+ };
210
+
211
+ NodeInfo {
212
+ node_type,
213
+ is_list: false,
214
+ value: None,
215
+ list_values: vec![],
216
+ location: entry_location,
217
+ key_name: entry_key_name,
218
+ key_location: entry_key_location,
219
+ }
220
+ }
109
221
  }
110
222
  }
111
223
 
@@ -166,28 +278,61 @@ impl Document {
166
278
  .collect()
167
279
  }
168
280
 
169
- pub fn get_value(&self, dot_path: &str) -> Option<serde_yaml::Value> {
281
+ pub fn get_value(&self, dot_path: &str) -> Option<yaml_serde::Value> {
170
282
  if dot_path.is_empty() {
171
283
  return Some(node_to_yaml_value(&self.root));
172
284
  }
173
285
 
174
- let nodes = self.navigate_all(dot_path);
286
+ let parsed = crate::selector::Selector::parse(dot_path);
175
287
 
176
- if nodes.is_empty() {
177
- return None;
178
- }
288
+ if parsed.has_wildcard() {
289
+ let padded = self.navigate_all(dot_path);
179
290
 
180
- if nodes.len() == 1 {
181
- return Some(node_to_yaml_value(&nodes[0]));
182
- }
291
+ if padded.is_empty() {
292
+ return None;
293
+ }
294
+
295
+ let values: Vec<yaml_serde::Value> = padded
296
+ .iter()
297
+ .map(|maybe_node| match maybe_node {
298
+ Some(node) => node_to_yaml_value(node),
299
+ None => yaml_serde::Value::Null,
300
+ })
301
+ .collect();
302
+
303
+ Some(yaml_serde::Value::Sequence(values))
304
+ } else {
305
+ let nodes = self.navigate_all_compact(dot_path);
183
306
 
184
- let values: Vec<serde_yaml::Value> = nodes.iter().map(node_to_yaml_value).collect();
307
+ if nodes.is_empty() {
308
+ return None;
309
+ }
310
+
311
+ if nodes.len() == 1 {
312
+ return Some(node_to_yaml_value(&nodes[0]));
313
+ }
185
314
 
186
- Some(serde_yaml::Value::Sequence(values))
315
+ let values: Vec<yaml_serde::Value> = nodes.iter().map(node_to_yaml_value).collect();
316
+
317
+ Some(yaml_serde::Value::Sequence(values))
318
+ }
187
319
  }
188
320
 
189
- pub fn get_values(&self, dot_path: &str) -> Vec<serde_yaml::Value> {
190
- self.navigate_all(dot_path).iter().map(node_to_yaml_value).collect()
321
+ pub fn get_values(&self, dot_path: &str) -> Vec<yaml_serde::Value> {
322
+ let parsed = crate::selector::Selector::parse(dot_path);
323
+
324
+ if parsed.has_wildcard() {
325
+ self
326
+ .navigate_all(dot_path)
327
+ .iter()
328
+ .map(|maybe_node| match maybe_node {
329
+ Some(node) => node_to_yaml_value(node),
330
+ None => yaml_serde::Value::Null,
331
+ })
332
+ .collect()
333
+ } else {
334
+ self.navigate_all_compact(dot_path).iter().map(node_to_yaml_value).collect()
335
+ }
191
336
  }
192
337
 
193
338
  pub fn selectors(&self) -> Vec<String> {
@@ -206,10 +351,33 @@ impl Document {
206
351
 
207
352
  pub fn exists(&self, dot_path: &str) -> bool {
208
353
  if dot_path.contains('[') {
209
- return !self.navigate_all(dot_path).is_empty();
354
+ if !self.navigate_all_compact(dot_path).is_empty() {
355
+ return true;
356
+ }
357
+ } else if self.navigate(dot_path).is_ok() {
358
+ return true;
210
359
  }
211
360
 
212
- self.get(dot_path).is_some()
361
+ self.find_entry(dot_path).is_some()
362
+ }
363
+
364
+ fn find_entry(&self, dot_path: &str) -> Option<SyntaxNode> {
365
+ let (parent_path, last_key) = match dot_path.rsplit_once('.') {
366
+ Some((parent, key)) => (parent, key),
367
+ None => ("", dot_path),
368
+ };
369
+
370
+ let parent_node = if parent_path.is_empty() {
371
+ let root = Root::cast(self.root.clone())?;
372
+ let document = root.documents().next()?;
373
+ document.syntax().clone()
374
+ } else {
375
+ self.navigate(parent_path).ok()?
376
+ };
377
+
378
+ let map = parent_node.descendants().find_map(BlockMap::cast)?;
379
+
380
+ find_entry_by_key(&map, last_key).map(|entry| entry.syntax().clone())
213
381
  }
214
382
 
215
383
  pub fn get_sequence_values(&self, dot_path: &str) -> Vec<String> {
@@ -260,3 +428,66 @@ impl Document {
260
428
  None
261
429
  }
262
430
  }
431
+
432
+ pub(crate) fn node_selector(node: &SyntaxNode) -> String {
433
+ let mut parts: Vec<String> = Vec::new();
434
+ let mut current = node.clone();
435
+
436
+ if current.kind() == SyntaxKind::BLOCK_SEQ_ENTRY {
437
+ if let Some(parent) = current.parent() {
438
+ let index = parent
439
+ .children()
440
+ .filter(|child| child.kind() == SyntaxKind::BLOCK_SEQ_ENTRY)
441
+ .position(|child| child == current)
442
+ .unwrap_or(0);
443
+
444
+ parts.push(format!("[{}]", index));
445
+ }
446
+ }
447
+
448
+ loop {
449
+ let parent = match current.parent() {
450
+ Some(parent) => parent,
451
+ None => break,
452
+ };
453
+
454
+ match parent.kind() {
455
+ SyntaxKind::BLOCK_SEQ_ENTRY => {
456
+ if let Some(grandparent) = parent.parent() {
457
+ let index = grandparent
458
+ .children()
459
+ .filter(|child| child.kind() == SyntaxKind::BLOCK_SEQ_ENTRY)
460
+ .position(|child| child == parent)
461
+ .unwrap_or(0);
462
+
463
+ parts.push(format!("[{}]", index));
464
+ }
465
+ }
466
+
467
+ SyntaxKind::BLOCK_MAP_ENTRY => {
468
+ if let Some(key_node) = parent.children().find(|child| child.kind() == SyntaxKind::BLOCK_MAP_KEY) {
469
+ if let Some(key_text) = extract_scalar_text(&key_node) {
470
+ parts.push(key_text);
471
+ }
472
+ }
473
+ }
474
+
475
+ _ => {}
476
+ }
477
+
478
+ current = parent;
479
+ }
480
+
481
+ parts.reverse();
482
+ let mut result = String::new();
483
+
484
+ for part in &parts {
485
+ if !part.starts_with('[') && !result.is_empty() {
486
+ result.push('.');
487
+ }
488
+
489
+ result.push_str(part);
490
+ }
491
+
492
+ result
493
+ }
@@ -22,9 +22,9 @@ impl Document {
22
22
  }
23
23
  }
24
24
 
25
- if let Some(serde_yaml::Value::Sequence(sequence)) = self.get_value(dot_path).as_ref() {
26
- if let Some(serde_yaml::Value::Mapping(map)) = sequence.first() {
27
- if let Some((serde_yaml::Value::String(key_name), _)) = map.iter().next() {
25
+ if let Some(yaml_serde::Value::Sequence(sequence)) = self.get_value(dot_path).as_ref() {
26
+ if let Some(yaml_serde::Value::Mapping(map)) = sequence.first() {
27
+ if let Some((yaml_serde::Value::String(key_name), _)) = map.iter().next() {
28
28
  let deep_path = if dot_path.is_empty() {
29
29
  format!("[].{}", key_name)
30
30
  } else {
@@ -2,9 +2,24 @@ mod condition;
2
2
  mod delete;
3
3
  mod get;
4
4
  mod insert;
5
+ mod schema;
5
6
  mod set;
6
7
  mod sort;
7
8
  mod style;
9
+ mod unique;
10
+ pub use unique::DuplicateInfo;
11
+
12
+ use crate::syntax::YerbaValueType;
13
+
14
+ #[derive(Debug, Clone)]
15
+ pub struct LocatedNode {
16
+ pub node_type: String,
17
+ pub text: Option<String>,
18
+ pub value_type: Option<YerbaValueType>,
19
+ pub file_path: Option<String>,
20
+ pub selector: String,
21
+ pub line: usize,
22
+ }
8
23
 
9
24
  use std::fs;
10
25
  use std::path::{Path, PathBuf};
@@ -19,8 +34,8 @@ use crate::error::YerbaError;
19
34
  use crate::QuoteStyle;
20
35
 
21
36
  use crate::syntax::{
22
- extract_scalar, extract_scalar_text, find_entry_by_key, find_scalar_token, format_scalar_value, is_map_key, is_yaml_non_string, preceding_whitespace_indent,
23
- removal_range, unescape_double_quoted, unescape_single_quoted, ScalarValue,
37
+ dedent_block_scalar, extract_scalar, extract_scalar_text, find_entry_by_key, find_scalar_token, format_scalar_value, is_map_key, is_yaml_non_string,
38
+ preceding_whitespace_indent, removal_range, unescape_double_quoted, unescape_single_quoted, ScalarValue,
24
39
  };
25
40
 
26
41
  #[derive(Debug, Clone)]
@@ -155,7 +170,7 @@ impl Document {
155
170
  return Ok(document.syntax().clone());
156
171
  }
157
172
 
158
- let nodes = self.navigate_all(dot_path);
173
+ let nodes = self.navigate_all_compact(dot_path);
159
174
 
160
175
  match nodes.len() {
161
176
  0 => Err(YerbaError::SelectorNotFound(dot_path.to_string())),
@@ -164,7 +179,11 @@ impl Document {
164
179
  }
165
180
  }
166
181
 
167
- pub fn navigate_all(&self, dot_path: &str) -> Vec<SyntaxNode> {
182
+ pub fn navigate_all_compact(&self, dot_path: &str) -> Vec<SyntaxNode> {
183
+ self.navigate_all(dot_path).into_iter().flatten().collect()
184
+ }
185
+
186
+ pub fn navigate_all(&self, dot_path: &str) -> Vec<Option<SyntaxNode>> {
168
187
  if Document::validate_path(dot_path).is_err() {
169
188
  return Vec::new();
170
189
  }
@@ -181,26 +200,63 @@ impl Document {
181
200
  None => return Vec::new(),
182
201
  };
183
202
 
184
- let mut current_nodes = vec![document.syntax().clone()];
203
+ let mut current_nodes: Vec<Option<SyntaxNode>> = vec![Some(document.syntax().clone())];
185
204
 
186
205
  if parsed.is_empty() {
187
206
  if let Some(sequence) = document.syntax().descendants().find_map(BlockSeq::cast) {
188
- current_nodes = sequence.entries().map(|entry| entry.syntax().clone()).collect();
207
+ current_nodes = sequence.entries().map(|entry| Some(entry.syntax().clone())).collect();
189
208
  }
190
209
 
191
210
  return current_nodes;
192
211
  }
193
212
 
194
- for segment in parsed.segments() {
195
- let mut next_nodes = Vec::new();
196
-
197
- for node in &current_nodes {
198
- next_nodes.extend(resolve_segment(node, segment));
213
+ let segments = parsed.segments();
214
+
215
+ for (i, segment) in segments.iter().enumerate() {
216
+ let is_wildcard = matches!(segment, crate::selector::SelectorSegment::AllItems);
217
+ let has_remaining = i + 1 < segments.len();
218
+ let mut next_nodes: Vec<Option<SyntaxNode>> = Vec::new();
219
+
220
+ for maybe_node in &current_nodes {
221
+ match maybe_node {
222
+ None => next_nodes.push(None),
223
+ Some(node) => {
224
+ let resolved = resolve_segment(node, segment);
225
+
226
+ if is_wildcard && has_remaining {
227
+ let remaining = &segments[i + 1..];
228
+
229
+ for item in &resolved {
230
+ let results = navigate_remaining(item, remaining);
231
+
232
+ if results.is_empty() {
233
+ next_nodes.push(None);
234
+ } else {
235
+ for result in results {
236
+ next_nodes.push(Some(result));
237
+ }
238
+ }
239
+ }
240
+
241
+ return next_nodes;
242
+ } else if is_wildcard {
243
+ for item in resolved {
244
+ next_nodes.push(Some(item));
245
+ }
246
+ } else if resolved.is_empty() {
247
+ return Vec::new();
248
+ } else {
249
+ for item in resolved {
250
+ next_nodes.push(Some(item));
251
+ }
252
+ }
253
+ }
254
+ }
199
255
  }
200
256
 
201
257
  current_nodes = next_nodes;
202
258
 
203
- if current_nodes.is_empty() {
259
+ if current_nodes.iter().all(|n| n.is_none()) {
204
260
  break;
205
261
  }
206
262
  }
@@ -389,11 +445,11 @@ pub(crate) fn compute_location(source: &str, start_offset: usize, end_offset: us
389
445
  }
390
446
  }
391
447
 
392
- pub fn collect_selectors(value: &serde_yaml::Value, prefix: &str, selectors: &mut Vec<String>) {
448
+ pub fn collect_selectors(value: &yaml_serde::Value, prefix: &str, selectors: &mut Vec<String>) {
393
449
  match value {
394
- serde_yaml::Value::Mapping(map) => {
450
+ yaml_serde::Value::Mapping(map) => {
395
451
  for (key, child) in map {
396
- if let serde_yaml::Value::String(key_string) = key {
452
+ if let yaml_serde::Value::String(key_string) = key {
397
453
  let selector = if prefix.is_empty() {
398
454
  key_string.clone()
399
455
  } else {
@@ -406,7 +462,7 @@ pub fn collect_selectors(value: &serde_yaml::Value, prefix: &str, selectors: &mu
406
462
  }
407
463
  }
408
464
 
409
- serde_yaml::Value::Sequence(sequence) => {
465
+ yaml_serde::Value::Sequence(sequence) => {
410
466
  let bracket_prefix = format!("{}[]", prefix);
411
467
  selectors.push(bracket_prefix.clone());
412
468
 
@@ -419,21 +475,21 @@ pub fn collect_selectors(value: &serde_yaml::Value, prefix: &str, selectors: &mu
419
475
  }
420
476
  }
421
477
 
422
- pub(crate) fn node_to_yaml_value(node: &SyntaxNode) -> serde_yaml::Value {
478
+ pub(crate) fn node_to_yaml_value(node: &SyntaxNode) -> yaml_serde::Value {
423
479
  if let Some(sequence) = node.descendants().find_map(BlockSeq::cast) {
424
480
  let map_position = node.descendants().find_map(BlockMap::cast).map(|map| map.syntax().text_range().start());
425
481
 
426
482
  let sequence_position = sequence.syntax().text_range().start();
427
483
 
428
484
  if map_position.is_none() || sequence_position <= map_position.unwrap() {
429
- let values: Vec<serde_yaml::Value> = sequence.entries().map(|entry| node_to_yaml_value(entry.syntax())).collect();
485
+ let values: Vec<yaml_serde::Value> = sequence.entries().map(|entry| node_to_yaml_value(entry.syntax())).collect();
430
486
 
431
- return serde_yaml::Value::Sequence(values);
487
+ return yaml_serde::Value::Sequence(values);
432
488
  }
433
489
  }
434
490
 
435
491
  if let Some(map) = node.descendants().find_map(BlockMap::cast) {
436
- let mut mapping = serde_yaml::Mapping::new();
492
+ let mut mapping = yaml_serde::Mapping::new();
437
493
 
438
494
  for entry in map.entries() {
439
495
  let key = entry.key().and_then(|key_node| extract_scalar_text(key_node.syntax())).unwrap_or_default();
@@ -441,18 +497,18 @@ pub(crate) fn node_to_yaml_value(node: &SyntaxNode) -> serde_yaml::Value {
441
497
  let value = entry
442
498
  .value()
443
499
  .map(|value_node| node_to_yaml_value(value_node.syntax()))
444
- .unwrap_or(serde_yaml::Value::Null);
500
+ .unwrap_or(yaml_serde::Value::Null);
445
501
 
446
- mapping.insert(serde_yaml::Value::String(key), value);
502
+ mapping.insert(yaml_serde::Value::String(key), value);
447
503
  }
448
504
 
449
- return serde_yaml::Value::Mapping(mapping);
505
+ return yaml_serde::Value::Mapping(mapping);
450
506
  }
451
507
 
452
508
  if let Some(sequence) = node.descendants().find_map(BlockSeq::cast) {
453
- let values: Vec<serde_yaml::Value> = sequence.entries().map(|entry| node_to_yaml_value(entry.syntax())).collect();
509
+ let values: Vec<yaml_serde::Value> = sequence.entries().map(|entry| node_to_yaml_value(entry.syntax())).collect();
454
510
 
455
- return serde_yaml::Value::Sequence(values);
511
+ return yaml_serde::Value::Sequence(values);
456
512
  }
457
513
 
458
514
  if let Some(block_scalar) = node.descendants().find(|child| child.kind() == SyntaxKind::BLOCK_SCALAR) {
@@ -463,35 +519,37 @@ pub(crate) fn node_to_yaml_value(node: &SyntaxNode) -> serde_yaml::Value {
463
519
  .map(|token| token.text().to_string())
464
520
  .unwrap_or_default();
465
521
 
466
- return serde_yaml::Value::String(text);
522
+ let text = dedent_block_scalar(&text);
523
+
524
+ return yaml_serde::Value::String(text);
467
525
  }
468
526
 
469
527
  if let Some(scalar) = extract_scalar(node) {
470
528
  use crate::syntax::{detect_yaml_type, is_yaml_truthy, YerbaValueType};
471
529
 
472
530
  return match detect_yaml_type(&scalar) {
473
- YerbaValueType::Null => serde_yaml::Value::Null,
474
- YerbaValueType::Boolean => serde_yaml::Value::Bool(is_yaml_truthy(&scalar.text)),
531
+ YerbaValueType::Null => yaml_serde::Value::Null,
532
+ YerbaValueType::Boolean => yaml_serde::Value::Bool(is_yaml_truthy(&scalar.text)),
475
533
 
476
534
  YerbaValueType::Integer => scalar
477
535
  .text
478
536
  .parse::<i64>()
479
- .map(|n| serde_yaml::Value::Number(serde_yaml::Number::from(n)))
480
- .unwrap_or(serde_yaml::Value::String(scalar.text)),
537
+ .map(|n| yaml_serde::Value::Number(yaml_serde::Number::from(n)))
538
+ .unwrap_or(yaml_serde::Value::String(scalar.text)),
481
539
 
482
540
  YerbaValueType::Float => scalar
483
541
  .text
484
542
  .parse::<f64>()
485
- .map(|n| serde_yaml::Value::Number(serde_yaml::Number::from(n)))
486
- .unwrap_or(serde_yaml::Value::String(scalar.text)),
543
+ .map(|n| yaml_serde::Value::Number(yaml_serde::Number::from(n)))
544
+ .unwrap_or(yaml_serde::Value::String(scalar.text)),
487
545
 
488
- YerbaValueType::String => serde_yaml::Value::String(scalar.text),
546
+ YerbaValueType::String => yaml_serde::Value::String(scalar.text),
489
547
  };
490
548
  }
491
549
 
492
550
  let text = node.text().to_string();
493
551
 
494
- serde_yaml::from_str(&text).unwrap_or(serde_yaml::Value::String(text))
552
+ yaml_serde::from_str(&text).unwrap_or(yaml_serde::Value::String(text))
495
553
  }
496
554
 
497
555
  pub(crate) fn parse_condition(condition: &str) -> Option<(String, &str, String)> {
@@ -516,6 +574,26 @@ pub(crate) fn parse_condition(condition: &str) -> Option<(String, &str, String)>
516
574
  Some((left.to_string(), operator, right.to_string()))
517
575
  }
518
576
 
577
+ fn navigate_remaining(node: &SyntaxNode, segments: &[crate::selector::SelectorSegment]) -> Vec<SyntaxNode> {
578
+ let mut current_nodes = vec![node.clone()];
579
+
580
+ for segment in segments {
581
+ let mut next_nodes = Vec::new();
582
+
583
+ for current in &current_nodes {
584
+ next_nodes.extend(resolve_segment(current, segment));
585
+ }
586
+
587
+ if next_nodes.is_empty() {
588
+ return Vec::new();
589
+ }
590
+
591
+ current_nodes = next_nodes;
592
+ }
593
+
594
+ current_nodes
595
+ }
596
+
519
597
  fn resolve_segment(node: &SyntaxNode, segment: &crate::selector::SelectorSegment) -> Vec<SyntaxNode> {
520
598
  use crate::selector::SelectorSegment;
521
599