Exemplo
postcss 8.5.26: Node#prev
Amostra verificada para npm postcss 8.5.26: Node#prev. O contrato rodou em node 22 · linux alpine/x64 · docker e passou: assert Node#prev returns undefined…
sha256:749f824d188b090e04c1de57637c1f626c802cf38b03d49c582cb17515de6df4
Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu.
Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas.
MIT-0
Evidência de execução
O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.
- Base da evidência
- Contrato assinado aprovado
- Recibos de verificação
- 1
- Chaves de assinatura que o compilaram
- 1
Ambiente declarado
node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10
Ambientes das execuções de verificação
| Ambiente | Contrato | Etapas | Execução |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-27 |
Caso
HOW- Objetivo
- verify Node#prev in pkg:npm/postcss@8.5.26
- Pacotes
- Símbolos
-
- Node#prev
- Ambiente
- node 22.23.2
- Criado
- 2026-08-27T02:00:43Z
Contrato
- assert Node#prev returns undefined for the first child in a container
- assert Node#prev returns undefined for an unattached or standalone node
- assert Node#prev returns the previous sibling Node for declarations within a rule
- assert Node#prev returns the previous sibling Node for rules and at-rules in root
- assert Node#prev enables backward traversal through container children
- assert Node#prev reflects AST mutations when siblings are removed or inserted
Arquivos
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.js
- test/contract.mjs
Código-fonte
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify Node#prev in pkg:npm/postcss@8.5.26
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/postcss@8.5.26
Demonstrate these symbols/APIs:
- Node#prev
Constraints:
- executionContext: node
Required runtime conditions:
- ecosystem: npm
- language: javascript
- moduleSystem: cjs
- packageManager: npm@10.9.8
- runtime: node@22.23.2
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:fbeb8a020fac184f0906f44acb03bf5e860c51dc172d1a2784f3e93fbcec21df","constraints":{"executionContext":"node"},"contract":["assert Node#prev returns undefined for the first child in a container","assert Node#prev returns undefined for an unattached or standalone node","assert Node#prev returns the previous sibling Node for declarations within a rule","assert Node#prev returns the previous sibling Node for rules and at-rules in root","assert Node#prev enables backward traversal through container children","assert Node#prev reflects AST mutations when siblings are removed or inserted"],"goal":"verify Node#prev in pkg:npm/postcss@8.5.26","kind":"HOW","packages":["pkg:npm/postcss@8.5.26"],"schemaVersion":1,"symbols":["Node#prev"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","executionContext":"node","language":"javascript","libc":"glibc","libcVersion":"2.39","moduleSystem":"esm","os":"linux","osVersionBucket":"24","packageManager":"npm","packageManagerVersion":"10.9.8","runtime":"node","runtimeVersion":"22.23.2","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/postcss@8.5.26"],"schemaVersion":1,"subject":"pkg:npm/postcss@8.5.26","symbols":["Node#prev"],"verifierAdapter":"node-typescript@1"}
{
"name": "sample-postcss-node-prev",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-postcss-node-prev",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"postcss": "8.5.26"
}
},
"node_modules/nanoid": {
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.5.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
"integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.17",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
}
}
}
{
"name": "sample-postcss-node-prev",
"version": "1.0.0",
"description": "Clean-room sample verifying Node#prev in postcss",
"main": "src/index.js",
"type": "module",
"license": "MIT-0",
"dependencies": {
"postcss": "8.5.26"
}
}
{
"schemaVersion": 1,
"goal": "verify Node#prev in pkg:npm/postcss@8.5.26",
"kind": "HOW",
"packages": [
"pkg:npm/postcss@8.5.26"
],
"symbols": [
"Node#prev"
],
"constraints": {
"executionContext": "node"
},
"runtimeConditions": {
"ecosystem": "npm",
"language": "javascript",
"moduleSystem": "cjs",
"packageManager": "npm@10.9.8",
"runtime": "node@22.23.2"
}
}
import postcss from 'postcss';
/**
* Returns the immediate previous sibling of a node in its parent container,
* or undefined if the node is the first child or unattached.
*
* @param {import('postcss').Node} node
* @returns {import('postcss').Node | undefined}
*/
export function getPreviousSibling(node) {
if (!node || typeof node.prev !== 'function') {
return undefined;
}
return node.prev();
}
/**
* Collects all preceding siblings of a node in the container,
* ordered from closest preceding sibling backwards to the first child.
*
* @param {import('postcss').Node} node
* @returns {import('postcss').Node[]}
*/
export function collectPrecedingSiblings(node) {
const preceding = [];
if (!node || typeof node.prev !== 'function') {
return preceding;
}
let current = node.prev();
while (current) {
preceding.push(current);
current = current.prev();
}
return preceding;
}
/**
* Traverses backwards from the given node to find the nearest preceding Declaration
* matching the given CSS property name.
*
* @param {import('postcss').Node} node
* @param {string} propName
* @returns {import('postcss').Declaration | undefined}
*/
export function findPreviousDeclaration(node, propName) {
if (!node || typeof node.prev !== 'function') {
return undefined;
}
let current = node.prev();
while (current) {
if (current.type === 'decl' && current.prop === propName) {
return current;
}
current = current.prev();
}
return undefined;
}
/**
* Checks if a node is the first child of its parent container.
*
* @param {import('postcss').Node} node
* @returns {boolean}
*/
export function isFirstChild(node) {
if (!node || !node.parent) {
return false;
}
return node.prev() === undefined;
}
import assert from 'node:assert/strict';
import postcss from 'postcss';
import {
getPreviousSibling,
collectPrecedingSiblings,
findPreviousDeclaration,
isFirstChild
} from '../src/index.js';
// 1. assert Node#prev returns undefined for the first child in a container
{
const css = `
.card {
display: flex;
margin: 10px;
padding: 5px;
}
`;
const root = postcss.parse(css);
const rule = root.first;
assert.ok(rule, 'Rule should exist in parsed CSS');
const firstDecl = rule.first;
assert.ok(firstDecl, 'Rule first child declaration should exist');
assert.equal(firstDecl.prop, 'display');
// Direct Node#prev call
assert.equal(firstDecl.prev(), undefined, 'First declaration prev() must return undefined');
assert.equal(getPreviousSibling(firstDecl), undefined, 'Helper must return undefined for first child');
assert.equal(isFirstChild(firstDecl), true, 'isFirstChild helper must return true for first declaration');
// Root's first child
assert.equal(rule.prev(), undefined, 'First child rule in root prev() must return undefined');
assert.equal(isFirstChild(rule), true, 'isFirstChild helper must return true for first rule in root');
}
// 2. assert Node#prev returns undefined for an unattached or standalone node
{
const standaloneDecl = postcss.decl({ prop: 'color', value: 'blue' });
const standaloneRule = postcss.rule({ selector: '.standalone' });
assert.equal(standaloneDecl.parent, undefined, 'Standalone decl should have no parent');
assert.equal(standaloneDecl.prev(), undefined, 'Unattached decl prev() must return undefined');
assert.equal(getPreviousSibling(standaloneDecl), undefined, 'Helper must return undefined for unattached decl');
assert.equal(isFirstChild(standaloneDecl), false, 'isFirstChild must return false for unattached decl');
assert.equal(standaloneRule.prev(), undefined, 'Unattached rule prev() must return undefined');
assert.equal(getPreviousSibling(standaloneRule), undefined, 'Helper must return undefined for unattached rule');
}
// 3. assert Node#prev returns the previous sibling Node for declarations within a rule
{
const css = `
.btn {
color: red;
/* button spacing */
margin-top: 4px;
margin-bottom: 8px;
}
`;
const root = postcss.parse(css);
const rule = root.first;
const colorDecl = rule.nodes[0];
const commentNode = rule.nodes[1];
const marginTopDecl = rule.nodes[2];
const marginBottomDecl = rule.nodes[3];
assert.equal(colorDecl.prev(), undefined, 'First child colorDecl.prev() is undefined');
assert.equal(commentNode.prev(), colorDecl, 'commentNode.prev() must return colorDecl');
assert.equal(marginTopDecl.prev(), commentNode, 'marginTopDecl.prev() must return commentNode');
assert.equal(marginBottomDecl.prev(), marginTopDecl, 'marginBottomDecl.prev() must return marginTopDecl');
assert.equal(getPreviousSibling(marginBottomDecl), marginTopDecl, 'getPreviousSibling helper returns marginTopDecl');
assert.equal(isFirstChild(marginBottomDecl), false, 'isFirstChild is false for non-first child');
// Test findPreviousDeclaration helper
const foundMarginTop = findPreviousDeclaration(marginBottomDecl, 'margin-top');
assert.equal(foundMarginTop, marginTopDecl, 'findPreviousDeclaration finds immediate preceding decl');
const foundColor = findPreviousDeclaration(marginBottomDecl, 'color');
assert.equal(foundColor, colorDecl, 'findPreviousDeclaration traverses past comment to find color');
const notFound = findPreviousDeclaration(marginBottomDecl, 'padding');
assert.equal(notFound, undefined, 'findPreviousDeclaration returns undefined for non-existent prop');
}
// 4. assert Node#prev returns the previous sibling Node for rules and at-rules in root
{
const css = `
@charset "UTF-8";
@import "theme.css";
.header { font-size: 18px; }
.footer { font-size: 12px; }
`;
const root = postcss.parse(css);
const charsetAtRule = root.nodes[0];
const importAtRule = root.nodes[1];
const headerRule = root.nodes[2];
const footerRule = root.nodes[3];
assert.equal(charsetAtRule.prev(), undefined, 'charsetAtRule.prev() must be undefined');
assert.equal(importAtRule.prev(), charsetAtRule, 'importAtRule.prev() must be charsetAtRule');
assert.equal(headerRule.prev(), importAtRule, 'headerRule.prev() must be importAtRule');
assert.equal(footerRule.prev(), headerRule, 'footerRule.prev() must be headerRule');
}
// 5. assert Node#prev enables backward traversal through container children
{
const css = `
.list {
item-1: 1;
item-2: 2;
item-3: 3;
item-4: 4;
}
`;
const root = postcss.parse(css);
const rule = root.first;
const item4 = rule.nodes[3];
const preceding = collectPrecedingSiblings(item4);
assert.equal(preceding.length, 3, 'item4 must have 3 preceding siblings');
assert.equal(preceding[0].prop, 'item-3', 'Closest preceding sibling is item-3');
assert.equal(preceding[1].prop, 'item-2', 'Second preceding sibling is item-2');
assert.equal(preceding[2].prop, 'item-1', 'Third preceding sibling is item-1');
// Manual while loop traversal
const traversalOrder = [];
let curr = rule.last;
while (curr) {
traversalOrder.push(curr.prop);
curr = curr.prev();
}
assert.deepEqual(traversalOrder, ['item-4', 'item-3', 'item-2', 'item-1'], 'Backward traversal visits items in reverse order');
}
// 6. assert Node#prev reflects AST mutations when siblings are removed or inserted
{
const css = `
.box {
width: 100px;
height: 200px;
opacity: 0.5;
}
`;
const root = postcss.parse(css);
const rule = root.first;
const widthDecl = rule.nodes[0];
const heightDecl = rule.nodes[1];
const opacityDecl = rule.nodes[2];
assert.equal(opacityDecl.prev(), heightDecl, 'Before removal, opacity prev is height');
// Remove height declaration
heightDecl.remove();
assert.equal(opacityDecl.prev(), widthDecl, 'After removing height, opacity prev dynamically becomes width');
assert.equal(heightDecl.prev(), undefined, 'Removed height node has no parent, prev() is undefined');
// Insert a new declaration before opacity
const zIndexDecl = postcss.decl({ prop: 'z-index', value: '10' });
opacityDecl.before(zIndexDecl);
assert.equal(opacityDecl.prev(), zIndexDecl, 'After inserting zIndex before opacity, opacity prev is zIndex');
assert.equal(zIndexDecl.prev(), widthDecl, 'zIndex prev is width');
}
console.log('All Node#prev contract assertions passed successfully.');
Seeder de origem
anônimo