Reputation: 131
Say I have a YAML document like this:
valid_true:
- true
- True
- TRUE
valid_false:
- false
- False
- FALSE
I'd like to end up with an object that correlates the parsed object keys to the line numbers from the YAML document that defined them. An output like this might work:
{
"valid_true": {
"value": [
{"value": true, line: 2},
{"value": true, line: 3},
{"value": true, line: 4}
],
"line": 1
},
"valid_false": {
"value": [
{"value": false, line: 7},
{"value": false, line: 8},
{"value": false, line: 9}
],
"line": 6
}
}
Is this possible with this library? Or will I need to fork / modify it?
Upvotes: 3
Views: 748
Reputation: 1405
You can use js-yaml-source-map for this.
import fs from "fs";
import yaml from "js-yaml";
import SourceMap from "js-yaml-source-map";
const data = fs.readFileSync("./example.yaml", "utf8");
const map = new SourceMap();
// pass map.listen() to the listener option
const loaded = yaml.load(data, { listener: map.listen() });
Upvotes: 1
Reputation: 76722
Many YAML libraries peform the task of loading in multiple stages:
After the last step the line information that you seek is normally no longer available. As long as you can hook into the loading task, by either influencing the construction of objects or by building on top of an exposed node structure, then what you want is relatively easy to do.
That is e.g. the case in PyYAML, the YAML 1.1 loader/dumper on which js-yaml originally was based. But js-yaml has been rewritten to support YAML 1.2 since then and the API, doesn't seem to have any options to "interfere" as described in the previous paragraph.
You might want to look into older (PyYAML based) versions of the library, to see if the API for them is more flexible. I have not looked at the details of the implementation, but my impression is that the rewrite did away with flexibility in favour of speed (not in itself a bad decision, but not something that helps use cases like yours).
If you are not restricted by javascript, then you might want to look at the NimYaml
or my own ruamel.yaml
(for Python). Those are YAML 1.2 loader/dumpers where I know for sure you can hook into the loading process as you'll need to do.
ruamel.yaml
, when used in the default round-trip mode, has line/column information already assigned to the objects constructed from YAML mappings and sequences and this can be relatively easily be extended to the available special scalar types used in round-tripping (these include most types including booleans). Alternatively, if your input is guaranteed to have whitespace and/or comment-only lines after the keys, as your example has, the actual linenumber of an item can of course be calculated on the basis of the start of the list.
Upvotes: 1