Skip to content

Instantly share code, notes, and snippets.

@arthurfiorette
Last active January 4, 2026 21:29
Show Gist options
  • Select an option

  • Save arthurfiorette/eaedd936f44b621435a1c0ed89d3f10c to your computer and use it in GitHub Desktop.

Select an option

Save arthurfiorette/eaedd936f44b621435a1c0ed89d3f10c to your computer and use it in GitHub Desktop.
`format-package-json` test extractor.
#!/usr/bin/env node
/**
* Extract Test Data from AVA Snapshot Markdown Files
*
* This script reads AVA's human-readable snapshot markdown files (.js.md) and
* extracts test cases with their input/output data as clean JSON objects.
*
* AVA generates two snapshot formats:
* 1. Binary .snap files (CBOR encoded, not human-readable)
* 2. Markdown .md files (human-readable, generated alongside .snap files)
*
* This script parses the markdown files which contain test data in two formats:
* - Object format: { input: `JSON`, output: `JSON` } - used by macro tests
* - String format: `JSON` - used by direct t.snapshot() calls (output only)
*
* The script:
* - Finds all .js.md files in tests/snapshots/
* - Parses markdown sections (## headers)
* - Extracts backtick-quoted JSON strings
* - Handles ␊ special character (visual line feed marker)
* - Outputs array of { testName, input, output } objects
*
* Output format:
* [
* {
* "testName": "Test description",
* "input": { ... }, // JSON object or null
* "output": { ... } // JSON object
* }
* ]
*
* Source project: https://github.com/keithamus/sort-package-json
*/
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const SNAPSHOT_DIR = path.join(__dirname, 'tests/snapshots')
/**
* Extract backtick-quoted strings from JavaScript object literals
*/
function extractBacktickString(text, key) {
// Match: key: `...`
const regex = new RegExp(`${key}:\\s*\`([\\s\\S]*?)\`(?:,|\\s*})`, 'm')
const match = text.match(regex)
if (!match) return null
// Replace ␊ with actual newlines and clean up
let str = match[1]
.replace(//g, '\n')
.replace(/\\n/g, '\n')
.trim()
try {
return JSON.parse(str)
} catch (e) {
return null
}
}
/**
* Parse AVA snapshot markdown format
*/
function parseSnapshotMd(content) {
const tests = []
// Split by ## headers
const sections = content.split(/^## /m).filter(Boolean)
for (const section of sections) {
const lines = section.split('\n')
const testName = lines[0].trim()
// Skip the header section
if (testName.includes('Snapshot report')) continue
// Get description from > quote
let description = testName
for (const line of lines) {
if (line.trim().startsWith('>')) {
description = line.trim().substring(1).trim()
break
}
}
// Find the indented code block (starts with 4+ spaces)
let codeBlock = ''
let inCodeBlock = false
for (let i = 1; i < lines.length; i++) {
const line = lines[i]
// Code blocks are indented with 4 spaces
if (line.startsWith(' ') || line.startsWith('\t')) {
inCodeBlock = true
codeBlock += line.substring(4) + '\n'
} else if (inCodeBlock && line.trim() === '') {
// Allow empty lines within code block
codeBlock += '\n'
} else if (inCodeBlock && !line.trim().startsWith('>')) {
// End of code block
break
}
}
if (!codeBlock.trim()) continue
// Try to extract input and output from object format: { input: `...`, output: `...` }
let input = extractBacktickString(codeBlock, 'input')
let output = extractBacktickString(codeBlock, 'output')
// If no input/output found, check if it's just a single backtick string (output only)
if (!input && !output) {
const singleStringMatch = codeBlock.match(/^\s*`([\s\S]*?)`\s*$/m)
if (singleStringMatch) {
const str = singleStringMatch[1]
.replace(//g, '\n')
.replace(/\\n/g, '\n')
.trim()
try {
output = JSON.parse(str)
// For output-only tests, we don't have input
input = null
} catch (e) {
// Skip if can't parse
continue
}
}
}
if (input || output) {
tests.push({
testName: description,
input,
output
})
}
}
return tests
}
/**
* Main execution
*/
function main() {
const allTests = []
// Find all .md snapshot files
const mdFiles = fs.readdirSync(SNAPSHOT_DIR)
.filter(f => f.endsWith('.js.md'))
.sort()
for (const file of mdFiles) {
const filePath = path.join(SNAPSHOT_DIR, file)
const content = fs.readFileSync(filePath, 'utf-8')
const tests = parseSnapshotMd(content)
allTests.push(...tests)
}
// Output as JSON
console.log(JSON.stringify(allTests, null, 2))
}
main()
// Script ran for: https://github.com/keithamus/sort-package-json/commit/e3f2370982fdd22fbf6d68ab8c9690f3a767f834
[
{
"testName": "Should sort `peerDependenciesMeta` as object.",
"input": {
"peerDependenciesMeta": {
"z": "z",
"e": "e",
"ch": "ch",
"a": "a"
}
},
"output": {
"peerDependenciesMeta": {
"a": "a",
"ch": "ch",
"e": "e",
"z": "z"
}
}
},
{
"testName": "Should sort `dependenciesMeta` as object.",
"input": {
"dependenciesMeta": {
"z": "z",
"e": "e",
"ch": "ch",
"a": "a"
}
},
"output": {
"dependenciesMeta": {
"a": "a",
"ch": "ch",
"e": "e",
"z": "z"
}
}
},
{
"testName": "Should sort `dependenciesMeta` as object.",
"input": {
"dependenciesMeta": {
"@z-package/package@1.2.3": "@z-package/package@1.2.3",
"c-package@1.2.3": "c-package@1.2.3",
"b-package-package@1.2.3": "b-package-package@1.2.3",
"@a-package/package@1.2.3": "@a-package/package@1.2.3",
"b-package@1.2.3": "b-package@1.2.3",
"@b-package/package": "@b-package/package",
"@e-package/package@1.2.3": "@e-package/package@1.2.3",
"@ch-package/package@1.2.3": "@ch-package/package@1.2.3",
"e-package@1.2.3": "e-package@1.2.3",
"ch-package@1.2.3": "ch-package@1.2.3"
}
},
"output": {
"dependenciesMeta": {
"@a-package/package@1.2.3": "@a-package/package@1.2.3",
"@b-package/package": "@b-package/package",
"@ch-package/package@1.2.3": "@ch-package/package@1.2.3",
"@e-package/package@1.2.3": "@e-package/package@1.2.3",
"@z-package/package@1.2.3": "@z-package/package@1.2.3",
"b-package@1.2.3": "b-package@1.2.3",
"b-package-package@1.2.3": "b-package-package@1.2.3",
"c-package@1.2.3": "c-package@1.2.3",
"ch-package@1.2.3": "ch-package@1.2.3",
"e-package@1.2.3": "e-package@1.2.3"
}
}
},
{
"testName": "Should sort `pnpm.overrides` as object.",
"input": {
"pnpm": {
"overrides": {
"@z-package/package@1.2.3": "@z-package/package@1.2.3",
"c-package@1.2.3": "c-package@1.2.3",
"b-package-package@1.2.3": "b-package-package@1.2.3",
"@a-package/package@1.2.3": "@a-package/package@1.2.3",
"b-package@1.2.3": "b-package@1.2.3",
"@b-package/package": "@b-package/package",
"@e-package/package@1.2.3": "@e-package/package@1.2.3",
"@ch-package/package@1.2.3": "@ch-package/package@1.2.3",
"e-package@1.2.3": "e-package@1.2.3",
"ch-package@1.2.3": "ch-package@1.2.3"
}
}
},
"output": {
"pnpm": {
"overrides": {
"@a-package/package@1.2.3": "@a-package/package@1.2.3",
"@b-package/package": "@b-package/package",
"@ch-package/package@1.2.3": "@ch-package/package@1.2.3",
"@e-package/package@1.2.3": "@e-package/package@1.2.3",
"@z-package/package@1.2.3": "@z-package/package@1.2.3",
"b-package@1.2.3": "b-package@1.2.3",
"b-package-package@1.2.3": "b-package-package@1.2.3",
"c-package@1.2.3": "c-package@1.2.3",
"ch-package@1.2.3": "ch-package@1.2.3",
"e-package@1.2.3": "e-package@1.2.3"
}
}
}
},
{
"testName": "Should sort `eslintConfig` as object.",
"input": {
"eslintConfig": {
"z": "z",
"env": "env",
"parser": "parser",
"parserOptions": "parserOptions",
"settings": "settings",
"plugins": "plugins",
"extends": "extends",
"rules": "rules",
"overrides": "overrides",
"globals": "globals",
"processor": "processor",
"noInlineConfig": "noInlineConfig",
"reportUnusedDisableDirectives": "reportUnusedDisableDirectives",
"a": "a"
}
},
"output": {
"eslintConfig": {
"env": "env",
"parser": "parser",
"parserOptions": "parserOptions",
"settings": "settings",
"plugins": "plugins",
"extends": "extends",
"rules": "rules",
"overrides": "overrides",
"globals": "globals",
"processor": "processor",
"noInlineConfig": "noInlineConfig",
"reportUnusedDisableDirectives": "reportUnusedDisableDirectives",
"a": "a",
"z": "z"
}
}
},
{
"testName": "Should sort `eslintConfig.rules` as object.",
"input": {
"eslintConfig": {
"rules": {
"z": "z",
"unknown-plugin/depth-1/depth-2": "unknown-plugin/depth-1/depth-2",
"unicorn/new-for-builtins": "unicorn/new-for-builtins",
"unicorn/prefer-includes": "unicorn/prefer-includes",
"for-direction": "for-direction",
"array-callback-return": "array-callback-return",
"yoda": "yoda",
"prettier/prettier": "prettier/prettier",
"react/display-name": "react/display-name",
"react/jsx-key": "react/jsx-key",
"a": "a"
}
}
},
"output": {
"eslintConfig": {
"rules": {
"a": "a",
"array-callback-return": "array-callback-return",
"for-direction": "for-direction",
"yoda": "yoda",
"z": "z",
"prettier/prettier": "prettier/prettier",
"react/display-name": "react/display-name",
"react/jsx-key": "react/jsx-key",
"unicorn/new-for-builtins": "unicorn/new-for-builtins",
"unicorn/prefer-includes": "unicorn/prefer-includes",
"unknown-plugin/depth-1/depth-2": "unknown-plugin/depth-1/depth-2"
}
}
}
},
{
"testName": "Should sort `eslintConfig.override[]` same as `eslintConfig`",
"input": null,
"output": {
"eslintConfig": {
"overrides": [
{
"files": "*.js",
"excludedFiles": "*.exclude.js",
"env": "env",
"parser": "parser",
"parserOptions": "parserOptions",
"settings": "settings",
"plugins": "plugins",
"extends": "extends",
"rules": "rules",
"overrides": "overrides",
"globals": "globals",
"processor": "processor",
"noInlineConfig": "noInlineConfig",
"reportUnusedDisableDirectives": "reportUnusedDisableDirectives",
"_": "this should still be the first element"
},
{
"files": "*.js",
"excludedFiles": "*.exclude.js",
"env": "env",
"parser": "parser",
"parserOptions": "parserOptions",
"settings": "settings",
"plugins": "plugins",
"extends": "extends",
"rules": "rules",
"overrides": "overrides",
"globals": "globals",
"processor": "processor",
"noInlineConfig": "noInlineConfig",
"reportUnusedDisableDirectives": "reportUnusedDisableDirectives",
"_": "this should still be the second element"
}
]
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"unknown": "./unknown.unknown",
"./path-not-really-makes-no-sense": {},
"types": "./types.d.ts",
"types@<=1": "./v1/types.d.ts"
}
},
"output": {
"exports": {
"./path-not-really-makes-no-sense": {},
"types": "./types.d.ts",
"types@<=1": "./v1/types.d.ts",
"unknown": "./unknown.unknown"
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"unknown": "./unknown.unknown",
"./path-not-really-makes-no-sense": {},
"types@<=1": "./v1/types.d.ts",
"types": "./types.d.ts"
}
},
"output": {
"exports": {
"./path-not-really-makes-no-sense": {},
"types@<=1": "./v1/types.d.ts",
"types": "./types.d.ts",
"unknown": "./unknown.unknown"
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"unknown": "./unknown.unknown",
"./path-not-really-makes-no-sense": {},
"default": "./default.js"
}
},
"output": {
"exports": {
"./path-not-really-makes-no-sense": {},
"unknown": "./unknown.unknown",
"default": "./default.js"
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"./deep": {
"unknown": "./unknown.unknown",
"./path-not-really-makes-no-sense": {},
"types": "./types.d.ts",
"types@<=1": "./v1/types.d.ts"
}
}
},
"output": {
"exports": {
"./deep": {
"./path-not-really-makes-no-sense": {},
"types": "./types.d.ts",
"types@<=1": "./v1/types.d.ts",
"unknown": "./unknown.unknown"
}
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"./deep": {
"unknown": "./unknown.unknown",
"./path-not-really-makes-no-sense": {},
"types@<=1": "./v1/types.d.ts",
"types": "./types.d.ts"
}
}
},
"output": {
"exports": {
"./deep": {
"./path-not-really-makes-no-sense": {},
"types@<=1": "./v1/types.d.ts",
"types": "./types.d.ts",
"unknown": "./unknown.unknown"
}
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"./deep": {
"unknown": "./unknown.unknown",
"./path-not-really-makes-no-sense": {},
"default": "./default.js"
}
}
},
"output": {
"exports": {
"./deep": {
"./path-not-really-makes-no-sense": {},
"unknown": "./unknown.unknown",
"default": "./default.js"
}
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"types": "./types.d.ts"
}
},
"output": {
"exports": {
"types": "./types.d.ts"
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"default": "./default.js"
}
},
"output": {
"exports": {
"default": "./default.js"
}
}
},
{
"testName": "Should sort `exports` as object.",
"input": {
"exports": {
"types": "./types.d.ts",
"default": "./default.js"
}
},
"output": {
"exports": {
"types": "./types.d.ts",
"default": "./default.js"
}
}
},
{
"testName": "Should sort `contributors[]` as `PeopleField`",
"input": null,
"output": {
"contributors": [
{
"name": "Keith Cirkel",
"email": "npm@keithcirkel.co.uk",
"url": "http://keithcirkel.co.uk/",
"_": "this should still be the first element",
"a": "a",
"z": "z"
},
{
"name": "Keith Cirkel",
"email": "npm@keithcirkel.co.uk",
"url": "http://keithcirkel.co.uk/",
"_": "this should still be the second element",
"a": "a",
"z": "z"
}
]
}
},
{
"testName": "Should sort `badges[]`",
"input": null,
"output": {
"badges": [
{
"description": "sort-package-json build status",
"url": "https://travis-ci.com/keithamus/sort-package-json",
"href": "https://travis-ci.com/keithamus/sort-package-json.svg",
"_": "this should still be the first element",
"a": "a",
"z": "z"
},
{
"description": "sort-package-json build status",
"url": "https://travis-ci.com/keithamus/sort-package-json",
"href": "https://travis-ci.com/keithamus/sort-package-json.svg",
"_": "this should still be the second element",
"a": "a",
"z": "z"
}
]
}
},
{
"testName": "Should sort fields",
"input": {
"$schema": "$schema",
"activationEvents": "activationEvents",
"assets": "assets",
"author": "author",
"ava": "ava",
"babel": "babel",
"badges": "badges",
"betterScripts": "betterScripts",
"bin": "bin",
"binary": "binary",
"browser": "browser",
"browserify": "browserify",
"browserslist": "browserslist",
"bugs": "bugs",
"bundleDependencies": "bundleDependencies",
"bundledDependencies": "bundledDependencies",
"c8": "c8",
"categories": "categories",
"commitlint": "commitlint",
"config": "config",
"contributes": "contributes",
"contributors": "contributors",
"cpu": "cpu",
"dependencies": "dependencies",
"dependenciesMeta": "dependenciesMeta",
"description": "description",
"devDependencies": "devDependencies",
"devEngines": "devEngines",
"directories": "directories",
"displayName": "displayName",
"engineStrict": "engineStrict",
"engines": "engines",
"eslintConfig": "eslintConfig",
"eslintIgnore": "eslintIgnore",
"example": "example",
"examplestyle": "examplestyle",
"exports": "exports",
"extensionDependencies": "extensionDependencies",
"extensionPack": "extensionPack",
"files": "files",
"flat": "flat",
"funding": "funding",
"galleryBanner": "galleryBanner",
"homepage": "homepage",
"husky": "husky",
"icon": "icon",
"imports": "imports",
"jest": "jest",
"jest-junit": "jest-junit",
"jest-stare": "jest-stare",
"jsdelivr": "jsdelivr",
"jsnext:main": "jsnext:main",
"keywords": "keywords",
"l10n": "l10n",
"languageName": "languageName",
"license": "license",
"lint-staged": "lint-staged",
"main": "main",
"maintainers": "maintainers",
"man": "man",
"markdown": "markdown",
"mocha": "mocha",
"module": "module",
"name": "name",
"nano-staged": "nano-staged",
"nodemonConfig": "nodemonConfig",
"npmPackageJsonLintConfig": "npmPackageJsonLintConfig",
"npmpackagejsonlint": "npmpackagejsonlint",
"npmpkgjsonlint": "npmpkgjsonlint",
"nyc": "nyc",
"oclif": "oclif",
"optionalDependencies": "optionalDependencies",
"os": "os",
"overrides": "overrides",
"packageManager": "packageManager",
"peerDependencies": "peerDependencies",
"peerDependenciesMeta": "peerDependenciesMeta",
"pnpm": "pnpm",
"pre-commit": "pre-commit",
"preferGlobal": "preferGlobal",
"prettier": "prettier",
"preview": "preview",
"private": "private",
"publishConfig": "publishConfig",
"publisher": "publisher",
"qna": "qna",
"react-native": "react-native",
"release": "release",
"remarkConfig": "remarkConfig",
"repository": "repository",
"resolutions": "resolutions",
"scripts": "scripts",
"sideEffects": "sideEffects",
"simple-git-hooks": "simple-git-hooks",
"source": "source",
"stableVersion": "stableVersion",
"style": "style",
"stylelint": "stylelint",
"svelte": "svelte",
"tap": "tap",
"type": "type",
"types": "types",
"typesVersions": "typesVersions",
"typings": "typings",
"umd:main": "umd:main",
"unpkg": "unpkg",
"version": "version",
"volta": "volta",
"workspaces": "workspaces",
"xo": "xo"
},
"output": {
"$schema": "$schema",
"name": "name",
"displayName": "displayName",
"version": "version",
"stableVersion": "stableVersion",
"private": "private",
"description": "description",
"categories": "categories",
"keywords": "keywords",
"homepage": "homepage",
"bugs": "bugs",
"repository": "repository",
"funding": "funding",
"license": "license",
"qna": "qna",
"author": "author",
"maintainers": "maintainers",
"contributors": "contributors",
"publisher": "publisher",
"sideEffects": "sideEffects",
"type": "type",
"imports": "imports",
"exports": "exports",
"main": "main",
"svelte": "svelte",
"umd:main": "umd:main",
"jsdelivr": "jsdelivr",
"unpkg": "unpkg",
"module": "module",
"source": "source",
"jsnext:main": "jsnext:main",
"browser": "browser",
"react-native": "react-native",
"types": "types",
"typesVersions": "typesVersions",
"typings": "typings",
"style": "style",
"example": "example",
"examplestyle": "examplestyle",
"assets": "assets",
"bin": "bin",
"man": "man",
"directories": "directories",
"files": "files",
"workspaces": "workspaces",
"binary": "binary",
"scripts": "scripts",
"betterScripts": "betterScripts",
"l10n": "l10n",
"contributes": "contributes",
"activationEvents": "activationEvents",
"husky": "husky",
"simple-git-hooks": "simple-git-hooks",
"pre-commit": "pre-commit",
"commitlint": "commitlint",
"lint-staged": "lint-staged",
"nano-staged": "nano-staged",
"config": "config",
"nodemonConfig": "nodemonConfig",
"browserify": "browserify",
"babel": "babel",
"browserslist": "browserslist",
"xo": "xo",
"prettier": "prettier",
"eslintConfig": "eslintConfig",
"eslintIgnore": "eslintIgnore",
"npmpkgjsonlint": "npmpkgjsonlint",
"npmPackageJsonLintConfig": "npmPackageJsonLintConfig",
"npmpackagejsonlint": "npmpackagejsonlint",
"release": "release",
"remarkConfig": "remarkConfig",
"stylelint": "stylelint",
"ava": "ava",
"jest": "jest",
"jest-junit": "jest-junit",
"jest-stare": "jest-stare",
"mocha": "mocha",
"nyc": "nyc",
"c8": "c8",
"tap": "tap",
"oclif": "oclif",
"resolutions": "resolutions",
"overrides": "overrides",
"dependencies": "dependencies",
"devDependencies": "devDependencies",
"dependenciesMeta": "dependenciesMeta",
"peerDependencies": "peerDependencies",
"peerDependenciesMeta": "peerDependenciesMeta",
"optionalDependencies": "optionalDependencies",
"bundledDependencies": "bundledDependencies",
"bundleDependencies": "bundleDependencies",
"extensionPack": "extensionPack",
"extensionDependencies": "extensionDependencies",
"flat": "flat",
"packageManager": "packageManager",
"engines": "engines",
"engineStrict": "engineStrict",
"devEngines": "devEngines",
"volta": "volta",
"languageName": "languageName",
"os": "os",
"cpu": "cpu",
"preferGlobal": "preferGlobal",
"publishConfig": "publishConfig",
"icon": "icon",
"badges": "badges",
"galleryBanner": "galleryBanner",
"preview": "preview",
"markdown": "markdown",
"pnpm": "pnpm"
}
},
{
"testName": "Should sort `prettier` as object.",
"input": {
"prettier": {
"overrides": [],
"trailingComma": "none",
"semi": false,
"z": "z",
"a": "a"
}
},
"output": {
"prettier": {
"a": "a",
"semi": false,
"trailingComma": "none",
"z": "z",
"overrides": []
}
}
},
{
"testName": "Should sort `prettier.override[]`",
"input": null,
"output": {
"prettier": {
"overrides": [
{
"_": "this should still the first element",
"a": "a",
"files": "",
"options": {},
"z": "z"
},
{
"_": "this should still the seconde element",
"a": "a",
"files": "",
"options": {},
"z": "z"
}
]
}
}
},
{
"testName": "Should sort `prettier.overrides[].options`",
"input": null,
"output": {
"prettier": {
"overrides": [
{
"options": {
"a": "a",
"semi": false,
"trailingComma": "none",
"z": "z"
}
}
]
}
}
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment