(f *File)
| 307 | } |
| 308 | |
| 309 | func fileToValue(f *File) (DaselValue, []scalarPos, error) { |
| 310 | var raw any |
| 311 | var scalars []scalarPos |
| 312 | |
| 313 | contents := []byte(f.Content) |
| 314 | switch f.RealExt { |
| 315 | case ".json": |
| 316 | if err := json.Unmarshal(contents, &raw); err != nil { |
| 317 | return nil, nil, err |
| 318 | } |
| 319 | // JSON is a strict YAML subset; reparse for positions. |
| 320 | var node yaml.Node |
| 321 | if err := yaml.Unmarshal(contents, &node); err == nil { |
| 322 | scalars = walkYAMLScalars(&node, strings.Split(f.Content, "\n")) |
| 323 | } |
| 324 | case ".yml", ".yaml": |
| 325 | // Rewrite folded `>` indicators to literal `|` so the parsed |
| 326 | // value preserves newlines. Position-mapping into source then |
| 327 | // works on a line-for-line basis instead of having to guess |
| 328 | // where folds happened. We use the parser itself to locate |
| 329 | // the indicators so the rewrite is precise. |
| 330 | rewritten, ferr := foldedToLiteral(contents) |
| 331 | if ferr != nil { |
| 332 | return nil, nil, ferr |
| 333 | } |
| 334 | var node yaml.Node |
| 335 | if uerr := yaml.Unmarshal(rewritten, &node); uerr != nil { |
| 336 | return nil, nil, uerr |
| 337 | } |
| 338 | if derr := node.Decode(&raw); derr != nil { |
| 339 | return nil, nil, derr |
| 340 | } |
| 341 | scalars = walkYAMLScalars(&node, strings.Split(string(rewritten), "\n")) |
| 342 | case ".toml": |
| 343 | if err := toml.Unmarshal(contents, &raw); err != nil { |
| 344 | return nil, nil, err |
| 345 | } |
| 346 | default: |
| 347 | return nil, nil, errors.New("unsupported file type") |
| 348 | } |
| 349 | |
| 350 | value, isMap := raw.(map[string]any) |
| 351 | if !isMap { |
| 352 | return nil, nil, errors.New("document root is not an object") |
| 353 | } |
| 354 | |
| 355 | return value, scalars, nil |
| 356 | } |
searching dependent graphs…