Пример
yaml 2.9.0: Manipulate YAML Document AST paths, preserve comments, control scalar styles, and transform nodes with visit in yaml
Проверенный пример — npm yaml 2.9.0: Manipulate YAML Document AST paths, preserve comments, control scalar styles, and transform nodes with visit in yaml.…
sha256:e48bea588f5dd5489beab783c6a88de0ad1b37a153accb93af38e0689dfd3a1d
Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла.
Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди.
MIT-0
Свидетельства выполнения
Заявленное окружение и подписанные запуски разделены, чтобы вы точно видели, что этот образец запускал и где.
- Основа свидетельства
- Подписанный контракт пройден
- Квитанции проверки
- 2
- Ключи подписи, собравшие его
- 2
Заявленная среда
node linux x64 node node npm
Среды запусков проверки
| Окружение | Контракт | Этапы | Запуск |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-17 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
Кейс
HOW- Цель
- Manipulate YAML Document AST paths, preserve comments, control scalar styles, and transform nodes with visit in yaml
- Пакеты
- Символы
-
- yaml.parseDocument
- yaml.Document
- yaml.visit
- yaml.Scalar
- Окружение
- node
- Создан
- 2026-08-17T14:47:12Z
Контракт
- yaml.parseDocument returns a Document AST whose scalar values can be read and mutated via path arrays while preserving existing comments upon serialization
- doc.getIn with keepScalar flag returns the AST Scalar node to allow inspecting and updating scalar formatting styles
- doc.addIn, doc.deleteIn, and doc.hasIn manipulate sequence and mapping AST nodes at nested paths
- yaml.visit traverses document AST nodes and removes targeted nodes when returning visit.REMOVE
- doc.toJS with mapAsMap: true converts YAML mapping structures to native JavaScript Map instances
Файлы
- NOTES.md
- csx.json
- package-lock.json
- package.json
- src/index.mjs
- test/contract.mjs
Исходный код
# Notes
## Search Known Solution Result
A search for `pkg:npm/yaml` returned an existing solution `sha256:2599e0d3b97c21e59a6f4de52c39dc7235d8c59d64db5fa9519e8114c1e197e6` covering `yaml.parse` and `yaml.stringify` schema options (YAML 1.2 boolean strings, merge keys, multi-document parsing errors, duplicate keys, and line width formatting). This sample investigates a distinct area: `Document` AST parsing, path-based manipulation, comment retention, scalar styling, and AST tree visitation.
## Pinned Release
- Package: `yaml`
- Pinned Version: `2.9.0`
## Observed Behaviour
In `yaml@2.9.0`:
1. `parseDocument(src)` returns a mutable `Document` Abstract Syntax Tree (AST). In-place updates via `doc.setIn(['path', 'to', 'key'], newValue)` preserve document header comments, top-level comments, and inline field comments upon serialization with `doc.toString()`.
2. Calling `doc.getIn(path, true)` returns the underlying `Scalar` AST node rather than the primitive value, exposing formatting controls such as `node.type = Scalar.QUOTE_DOUBLE` or `node.type = Scalar.BLOCK_LITERAL`.
3. Collection navigation supports path-based inspection and manipulation: `doc.hasIn(path)` returns a boolean indicating path existence, `doc.addIn(path, value)` appends elements to sequence nodes, and `doc.deleteIn(path)` removes items by index or mapping key while shifting remaining sequence elements.
4. `visit(doc, visitor)` performs depth-first AST traversal across `Document`, `YAMLMap`, `YAMLSeq`, and `Scalar` nodes. Returning `visit.REMOVE` inside a node visitor callback cleanly removes that node from its parent collection.
5. Calling `doc.toJS({ mapAsMap: true })` produces native JavaScript `Map` instances for all nested mapping structures, preserving key insertion order.
{"case":{"caseId":"case:sha256:7c83a0b9d927afb9c755f5b3f2257692a237216e46736d2e1d0e66a4844c50ec","contract":["yaml.parseDocument returns a Document AST whose scalar values can be read and mutated via path arrays while preserving existing comments upon serialization","doc.getIn with keepScalar flag returns the AST Scalar node to allow inspecting and updating scalar formatting styles","doc.addIn, doc.deleteIn, and doc.hasIn manipulate sequence and mapping AST nodes at nested paths","yaml.visit traverses document AST nodes and removes targeted nodes when returning visit.REMOVE","doc.toJS with mapAsMap: true converts YAML mapping structures to native JavaScript Map instances"],"goal":"Manipulate YAML Document AST paths, preserve comments, control scalar styles, and transform nodes with visit in yaml","kind":"HOW","packages":["pkg:npm/yaml@2.9.0"],"schemaVersion":1,"symbols":["yaml.parseDocument","yaml.Document","yaml.visit","yaml.Scalar"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/yaml@2.9.0"],"schemaVersion":1,"symbols":["yaml.parseDocument","yaml.Document","yaml.visit","yaml.Scalar"],"verifierAdapter":"node-typescript@1"}
{
"name": "sample-npm-yaml-version-depth",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-npm-yaml-version-depth",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"yaml": "2.9.0"
}
},
"node_modules/yaml": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
"integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
},
"funding": {
"url": "https://github.com/sponsors/eemeli"
}
}
}
}
{
"name": "sample-npm-yaml-version-depth",
"version": "1.0.0",
"private": true,
"type": "module",
"license": "MIT-0",
"dependencies": {
"yaml": "2.9.0"
}
}
import YAML from 'yaml';
import {
parseDocument,
Document,
visit,
Scalar,
isDocument,
isScalar,
isMap,
isSeq,
} from 'yaml';
/**
* Parses a YAML string into a Document AST.
*/
export function parseDoc(src, options) {
return parseDocument(src, options);
}
/**
* Creates a new empty or initialized YAML Document AST.
*/
export function createDoc(value, options) {
return new Document(value, options);
}
/**
* Gets a nested value or AST node along a path.
* When keepScalar is true, returns the AST node (Scalar, YAMLMap, YAMLSeq).
*/
export function getDocPath(doc, path, keepScalar = false) {
return doc.getIn(path, keepScalar);
}
/**
* Sets a nested value along a path, mutating AST while preserving surrounding comments.
*/
export function setDocPath(doc, path, value) {
doc.setIn(path, value);
return doc;
}
/**
* Appends a value to a sequence node along a path.
*/
export function addDocPath(doc, path, value) {
doc.addIn(path, value);
return doc;
}
/**
* Deletes a nested entry or sequence element along a path.
*/
export function deleteDocPath(doc, path) {
return doc.deleteIn(path);
}
/**
* Checks whether a path exists in the document AST.
*/
export function hasDocPath(doc, path) {
return doc.hasIn(path);
}
/**
* Sets the scalar style (e.g. Scalar.QUOTE_DOUBLE, Scalar.BLOCK_LITERAL) on a node at the specified path.
*/
export function setScalarStyle(doc, path, styleType) {
const node = doc.getIn(path, true);
if (isScalar(node)) {
node.type = styleType;
}
return doc;
}
/**
* Traverses and transforms the document AST with a visitor.
*/
export function transformDoc(doc, visitor) {
visit(doc, visitor);
return doc;
}
/**
* Converts Document AST to JavaScript value (object, array, or Map).
*/
export function docToJS(doc, options = {}) {
return doc.toJS(options);
}
/**
* Serializes Document AST back to YAML string.
*/
export function docToString(doc) {
return doc.toString();
}
export { YAML, Scalar, Document, parseDocument, visit, isDocument, isScalar, isMap, isSeq };
export default YAML;
import { strict as assert } from 'node:assert';
import YAML, {
parseDoc,
createDoc,
getDocPath,
setDocPath,
addDocPath,
deleteDocPath,
hasDocPath,
setScalarStyle,
transformDoc,
docToJS,
docToString,
Scalar,
isDocument,
isScalar,
isMap,
isSeq,
visit,
} from '../src/index.mjs';
// Section 1: parseDocument and path-based mutation preserving comments
const sampleYaml = `# Service configuration
app:
# Primary endpoint
server: example.com
port: 8080
description: Fast web service
tags:
- web
- api
- deprecated_flag
`;
const doc = parseDoc(sampleYaml);
assert.ok(isDocument(doc), 'doc should be an instance of YAML Document');
// Verify reading values via getIn
assert.strictEqual(getDocPath(doc, ['app', 'port']), 8080, 'getDocPath retrieves primitive number');
assert.strictEqual(getDocPath(doc, ['app', 'server']), 'example.com', 'getDocPath retrieves primitive string');
// Mutate values in-place
setDocPath(doc, ['app', 'port'], 9443);
setDocPath(doc, ['app', 'server'], 'example.org');
doc.commentBefore = ' Global header';
const serializedMutated = docToString(doc);
assert.ok(serializedMutated.includes('# Global header'), 'Document header comment preserved');
assert.ok(serializedMutated.includes('# Service configuration'), 'Top-level key comment preserved');
assert.ok(serializedMutated.includes('# Primary endpoint'), 'Nested property comment preserved');
assert.ok(serializedMutated.includes('server: example.org'), 'Server field updated in serialized output');
assert.ok(serializedMutated.includes('port: 9443'), 'Port field updated in serialized output');
// Section 2: AST Scalar node inspection and style modification
const serverScalar = getDocPath(doc, ['app', 'server'], true);
assert.ok(isScalar(serverScalar), 'getDocPath with keepScalar=true returns Scalar node');
assert.strictEqual(serverScalar.value, 'example.org', 'Scalar node contains expected value');
// Modify scalar formatting styles
setScalarStyle(doc, ['app', 'server'], Scalar.QUOTE_DOUBLE);
setScalarStyle(doc, ['app', 'description'], Scalar.BLOCK_LITERAL);
const serializedStyled = docToString(doc);
assert.ok(serializedStyled.includes('server: "example.org"'), 'Double-quoted scalar style applied');
assert.ok(
serializedStyled.includes('description: |-\n Fast web service'),
'Block literal scalar style applied'
);
// Section 3: Sequence and mapping navigation (hasIn, addIn, deleteIn)
assert.strictEqual(hasDocPath(doc, ['app', 'tags']), true, 'hasDocPath returns true for existing sequence');
assert.strictEqual(hasDocPath(doc, ['app', 'database']), false, 'hasDocPath returns false for missing path');
// Append to sequence
addDocPath(doc, ['app', 'tags'], 'metrics');
assert.strictEqual(getDocPath(doc, ['app', 'tags', 3]), 'metrics', 'addDocPath appends item to sequence');
// Delete sequence element by index
const deletedWeb = deleteDocPath(doc, ['app', 'tags', 0]);
assert.strictEqual(deletedWeb, true, 'deleteDocPath returns true on successful deletion');
assert.strictEqual(getDocPath(doc, ['app', 'tags', 0]), 'api', 'Sequence shifts after index deletion');
assert.strictEqual(getDocPath(doc, ['app', 'tags', 1]), 'deprecated_flag', 'Second item shifted to index 1');
assert.strictEqual(getDocPath(doc, ['app', 'tags', 2]), 'metrics', 'Appended item at index 2');
// Section 4: AST traversal and node transformation using visit
const visitedValues = [];
transformDoc(doc, {
Scalar(key, node) {
if (typeof node.value === 'string' || typeof node.value === 'number') {
visitedValues.push(node.value);
}
// Remove deprecated_flag tag during traversal
if (node.value === 'deprecated_flag') {
return visit.REMOVE;
}
},
});
assert.ok(
visitedValues.includes('example.org'),
'visit traversed server scalar'
);
assert.ok(
visitedValues.includes('deprecated_flag'),
'visit traversed deprecated_flag scalar'
);
const tagsSeq = getDocPath(doc, ['app', 'tags']);
assert.ok(isSeq(tagsSeq), 'tagsSeq is a YAMLSeq');
assert.strictEqual(
tagsSeq.items.length,
2,
'visit.REMOVE successfully removed deprecated_flag scalar from sequence'
);
assert.strictEqual(
getDocPath(doc, ['app', 'tags', 0]),
'api',
'First item in tags is api'
);
assert.strictEqual(
getDocPath(doc, ['app', 'tags', 1]),
'metrics',
'Second item in tags is metrics'
);
// Section 5: Native JS conversion (Plain Object vs Map)
const plainJS = docToJS(doc);
assert.strictEqual(typeof plainJS, 'object', 'docToJS returns standard JavaScript object');
assert.strictEqual(plainJS.app.server, 'example.org');
assert.strictEqual(plainJS.app.port, 9443);
assert.deepStrictEqual(plainJS.app.tags, ['api', 'metrics']);
const mapJS = docToJS(doc, { mapAsMap: true });
assert.ok(mapJS instanceof Map, 'docToJS with mapAsMap: true returns Map instance');
assert.ok(mapJS.get('app') instanceof Map, 'Nested mappings return Map instances');
assert.strictEqual(mapJS.get('app').get('port'), 9443, 'Map instance contains correct value');
assert.deepStrictEqual(mapJS.get('app').get('tags'), ['api', 'metrics'], 'Sequence inside Map is an array');
console.log('CONTRACT PASS: yaml Document AST manipulation, comments, scalar styles, and visit');