yerba 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
 
@@ -171,23 +283,56 @@ impl Document {
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<serde_yaml::Value> = padded
296
+ .iter()
297
+ .map(|maybe_node| match maybe_node {
298
+ Some(node) => node_to_yaml_value(node),
299
+ None => serde_yaml::Value::Null,
300
+ })
301
+ .collect();
302
+
303
+ Some(serde_yaml::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<serde_yaml::Value> = nodes.iter().map(node_to_yaml_value).collect();
316
+
317
+ Some(serde_yaml::Value::Sequence(values))
318
+ }
187
319
  }
188
320
 
189
321
  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()
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 => serde_yaml::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
+ }
@@ -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
  }
@@ -463,6 +519,8 @@ 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
 
522
+ let text = dedent_block_scalar(&text);
523
+
466
524
  return serde_yaml::Value::String(text);
467
525
  }
468
526
 
@@ -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
 
@@ -0,0 +1,73 @@
1
+ use super::*;
2
+
3
+ impl Document {
4
+ pub fn validate_schema(&self, schema: &serde_json::Value, items: bool, selector: Option<&str>) -> Vec<crate::schema::ValidationError> {
5
+ let path = selector.unwrap_or("");
6
+ let has_wildcard = crate::selector::Selector::parse(path).has_wildcard();
7
+
8
+ let value = match self.get_value(path) {
9
+ Some(value) => crate::json::yaml_to_json(&value),
10
+ None => return vec![],
11
+ };
12
+
13
+ let validate_items = items || has_wildcard;
14
+
15
+ let mut errors = if validate_items {
16
+ match value.as_array() {
17
+ Some(array) => crate::schema::validate_array(array, schema),
18
+ None if value.is_null() => vec![crate::schema::ValidationError {
19
+ path: String::new(),
20
+ message: "expected an array but document is empty or not a sequence".to_string(),
21
+ item_label: None,
22
+ line: None,
23
+ }],
24
+ None => crate::schema::validate_array(std::slice::from_ref(&value), schema),
25
+ }
26
+ } else {
27
+ if value.is_null() {
28
+ return vec![];
29
+ }
30
+
31
+ crate::schema::validate_value(&value, schema)
32
+ };
33
+
34
+ let source = self.to_string();
35
+
36
+ for error in &mut errors {
37
+ if !error.path.is_empty() {
38
+ let selector = json_pointer_to_selector(&error.path);
39
+
40
+ if let Ok(node) = self.navigate(&selector) {
41
+ let offset: usize = node.text_range().start().into();
42
+ let line = source[..offset].chars().filter(|c| *c == '\n').count() + 1;
43
+
44
+ error.line = Some(line);
45
+ }
46
+ }
47
+ }
48
+
49
+ errors
50
+ }
51
+ }
52
+
53
+ fn json_pointer_to_selector(pointer: &str) -> String {
54
+ pointer
55
+ .strip_prefix('/')
56
+ .unwrap_or(pointer)
57
+ .split('/')
58
+ .map(|segment| {
59
+ if let Ok(index) = segment.parse::<usize>() {
60
+ format!("[{}]", index)
61
+ } else {
62
+ segment.to_string()
63
+ }
64
+ })
65
+ .fold(String::new(), |mut path, segment| {
66
+ if !path.is_empty() && !segment.starts_with('[') {
67
+ path.push('.');
68
+ }
69
+
70
+ path.push_str(&segment);
71
+ path
72
+ })
73
+ }
@@ -26,7 +26,7 @@ impl Document {
26
26
  }
27
27
 
28
28
  pub fn set_all(&mut self, dot_path: &str, value: &str) -> Result<(), YerbaError> {
29
- let nodes = self.navigate_all(dot_path);
29
+ let nodes = self.navigate_all_compact(dot_path);
30
30
 
31
31
  if nodes.is_empty() {
32
32
  return Err(YerbaError::SelectorNotFound(dot_path.to_string()));
@@ -113,12 +113,15 @@ impl Document {
113
113
  return self.validate_each_sort_keys(sequence_path, key_order);
114
114
  }
115
115
 
116
- let current_node = self.navigate(dot_path)?;
116
+ let current_node = match self.navigate(dot_path) {
117
+ Ok(node) => node,
118
+ Err(_) => return Ok(()),
119
+ };
117
120
 
118
- let map = current_node
119
- .descendants()
120
- .find_map(BlockMap::cast)
121
- .ok_or_else(|| YerbaError::SelectorNotFound(dot_path.to_string()))?;
121
+ let map = match current_node.descendants().find_map(BlockMap::cast) {
122
+ Some(map) => map,
123
+ None => return Ok(()),
124
+ };
122
125
 
123
126
  let unknown_keys: Vec<String> = map
124
127
  .entries()
@@ -138,12 +141,15 @@ impl Document {
138
141
  return self.sort_each_keys(sequence_path, key_order);
139
142
  }
140
143
 
141
- let current_node = self.navigate(dot_path)?;
144
+ let current_node = match self.navigate(dot_path) {
145
+ Ok(node) => node,
146
+ Err(_) => return Ok(()),
147
+ };
142
148
 
143
- let map = current_node
144
- .descendants()
145
- .find_map(BlockMap::cast)
146
- .ok_or_else(|| YerbaError::SelectorNotFound(dot_path.to_string()))?;
149
+ let map = match current_node.descendants().find_map(BlockMap::cast) {
150
+ Some(map) => map,
151
+ None => return Ok(()),
152
+ };
147
153
 
148
154
  let entries: Vec<_> = map.entries().collect();
149
155
 
@@ -202,7 +208,7 @@ impl Document {
202
208
  Err(_) => return Ok(()),
203
209
  }
204
210
  } else {
205
- let found = self.navigate_all(dot_path);
211
+ let found = self.navigate_all_compact(dot_path);
206
212
  if found.is_empty() {
207
213
  return Ok(());
208
214
  }
@@ -307,7 +313,7 @@ impl Document {
307
313
  Err(_) => return Ok(()),
308
314
  }
309
315
  } else {
310
- let found = self.navigate_all(dot_path);
316
+ let found = self.navigate_all_compact(dot_path);
311
317
  if found.is_empty() {
312
318
  return Ok(());
313
319
  }
@@ -438,7 +444,7 @@ impl Document {
438
444
  (dot_path, "")
439
445
  };
440
446
 
441
- let parent_nodes = self.navigate_all(parent_path);
447
+ let parent_nodes = self.navigate_all_compact(parent_path);
442
448
  let source = self.root.text().to_string();
443
449
  let mut edits: Vec<(TextRange, String)> = Vec::new();
444
450
 
@@ -3,7 +3,7 @@ use super::*;
3
3
  impl Document {
4
4
  pub fn enforce_blank_lines(&mut self, dot_path: &str, blank_lines: usize) -> Result<(), YerbaError> {
5
5
  let nodes = if dot_path.contains('[') {
6
- self.navigate_all(dot_path)
6
+ self.navigate_all_compact(dot_path)
7
7
  } else {
8
8
  vec![self.navigate(dot_path)?]
9
9
  };
@@ -105,7 +105,7 @@ impl Document {
105
105
  let source = self.root.text().to_string();
106
106
 
107
107
  let scope_ranges: Vec<TextRange> = match dot_path {
108
- Some(path) if !path.is_empty() => self.navigate_all(path).iter().map(|node| node.text_range()).collect(),
108
+ Some(path) if !path.is_empty() => self.navigate_all_compact(path).iter().map(|node| node.text_range()).collect(),
109
109
  _ => vec![self.root.text_range()],
110
110
  };
111
111
 
@@ -219,7 +219,7 @@ impl Document {
219
219
  let source = self.root.text().to_string();
220
220
 
221
221
  let scope_ranges: Vec<TextRange> = match dot_path {
222
- Some(path) if !path.is_empty() => self.navigate_all(path).iter().map(|node| node.text_range()).collect(),
222
+ Some(path) if !path.is_empty() => self.navigate_all_compact(path).iter().map(|node| node.text_range()).collect(),
223
223
  _ => vec![self.root.text_range()],
224
224
  };
225
225