샘플
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. node 22 …
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');