CodeSampleX

示例

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. contract 在 node…

sha256:e48bea588f5dd5489beab783c6a88de0ad1b37a153accb93af38e0689dfd3a1d

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 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

契约

  1. yaml.parseDocument returns a Document AST whose scalar values can be read and mutated via path arrays while preserving existing comments upon serialization
  2. doc.getIn with keepScalar flag returns the AST Scalar node to allow inspecting and updating scalar formatting styles
  3. doc.addIn, doc.deleteIn, and doc.hasIn manipulate sequence and mapping AST nodes at nested paths
  4. yaml.visit traverses document AST nodes and removes targeted nodes when returning visit.REMOVE
  5. 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

下载源代码构件 (tar.gz)

源代码

NOTES.md
# 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.
csx.json
{"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"}
package-lock.json
{
  "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"
      }
    }
  }
}
package.json
{
  "name": "sample-npm-yaml-version-depth",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "license": "MIT-0",
  "dependencies": {
    "yaml": "2.9.0"
  }
}
src/index.mjs
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;
test/contract.mjs
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');

原始种子者

csx-seed