"use strict";
/* Socket Lib - Built with rolldown */
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_primordials_object = require('../primordials/object.js');
const require_primordials_json = require('../primordials/json.js');

//#region src/json/format.ts
/**
* @file Shared utilities for JSON formatting preservation and manipulation.
*   Provides functions for detecting and preserving indentation, line endings,
*   and determining when JSON files should be saved based on content changes.
*/
/**
* Symbols used to store formatting metadata in JSON objects.
*/
const INDENT_SYMBOL = Symbol.for("indent");
const NEWLINE_SYMBOL = Symbol.for("newline");
/**
* Detect indentation from a JSON string. Supports space-based indentation
* (returns count) or mixed indentation (returns string).
*
* @example
*   ;```ts
*   detectIndent('{\n  "key": "value"\n}') // => 2
*   detectIndent('{\n    "key": "value"\n}') // => 4
*   detectIndent('{\n\t"key": "value"\n}') // => '\t'
*   ```
*
* @param json - JSON string to analyze.
*
* @returns Number of spaces or indentation string, defaults to 2 if not
*   detected.
*/
function detectIndent(json) {
	const match = json.match(/^[{[][\r\n]+(\s+)/m);
	if (!match) return 2;
	const indent = match[1];
	if (/^ +$/.test(indent)) return indent.length;
	return indent;
}
/**
* Detect newline character(s) from a JSON string. Supports LF (\n) and CRLF
* (\r\n) line endings.
*
* @example
*   ;```ts
*   detectNewline('{\n  "key": "value"\n}') // => '\n'
*   detectNewline('{\r\n  "key": "value"\r\n}') // => '\r\n'
*   ```
*
* @param json - JSON string to analyze.
*
* @returns Line ending string ('\n' or '\r\n'), defaults to '\n' if not
*   detected.
*/
function detectNewline(json) {
	const match = json.match(/\r?\n/);
	return match ? match[0] : "\n";
}
/**
* Extract formatting metadata from a JSON string.
*
* @example
*   ;```ts
*   const formatting = extractFormatting('{\n  "key": "value"\n}')
*   // => { indent: 2, newline: '\n' }
*   ```
*
* @param json - JSON string to analyze.
*
* @returns Object containing indent and newline formatting
*/
function extractFormatting(json) {
	return {
		indent: detectIndent(json),
		newline: detectNewline(json)
	};
}
/**
* Get default formatting for JSON files.
*
* @example
*   ;```typescript
*   const fmt = getDefaultFormatting()
*   // { indent: 2, newline: '\n' }
*   ```
*
* @returns Default formatting (2 spaces, LF line endings)
*/
function getDefaultFormatting() {
	return {
		indent: 2,
		newline: "\n"
	};
}
/**
* Extract formatting from content object that has symbol-based metadata.
*
* @example
*   ;```typescript
*   const content = {
*     [Symbol.for('indent')]: 4,
*     [Symbol.for('newline')]: '\r\n',
*   }
*   getFormattingFromContent(content) // { indent: 4, newline: "\r\n" }
*   ```
*
* @param content - Content object with Symbol.for('indent') and
*   Symbol.for('newline')
*
* @returns Formatting metadata, or defaults if symbols not present
*/
function getFormattingFromContent(content) {
	const indent = content[INDENT_SYMBOL];
	const newline = content[NEWLINE_SYMBOL];
	return {
		indent: indent === void 0 || indent === null ? 2 : indent,
		newline: newline === void 0 || newline === null ? "\n" : newline
	};
}
/**
* Determine if content should be saved based on changes and options. Compares
* current content with original content and respects options like
* ignoreWhitespace and sort.
*
* @example
*   ;```ts
*   const current = { key: 'new-value', [Symbol.for('indent')]: 2 }
*   const original = { key: 'old-value', [Symbol.for('indent')]: 2 }
*   shouldSave(current, original, '{\n  "key": "old-value"\n}\n')
*   // => true
*   ```
*
* @param currentContent - Current content object (may include formatting
*   symbols)
* @param originalContent - Original content for comparison (may include
*   formatting symbols)
* @param originalFileContent - Original file content as string (for whitespace
*   comparison)
* @param options - Options controlling save behavior.
*
* @returns True if content should be saved, false otherwise
*/
function shouldSave(currentContent, originalContent, originalFileContent, options = {}) {
	const { ignoreWhitespace = false, sort = false, sortFn } = options;
	const content = stripFormattingSymbols(currentContent);
	const sortedContent = sortFn ? sortFn(content) : sort ? sortKeys(content) : content;
	const origContent = originalContent ? stripFormattingSymbols(originalContent) : {};
	if (ignoreWhitespace) return !require("node:util").isDeepStrictEqual(sortedContent, origContent);
	return stringifyWithFormatting(sortedContent, getFormattingFromContent(currentContent)).trim() !== originalFileContent.trim();
}
/**
* Sort object keys alphabetically. Creates a new object with sorted keys (does
* not mutate input).
*
* @example
*   ;```ts
*   sortKeys({ z: 3, a: 1, m: 2 })
*   // => { a: 1, m: 2, z: 3 }
*   ```
*
* @param obj - Object to sort.
*
* @returns New object with alphabetically sorted keys
*/
function sortKeys(obj) {
	const sorted = { __proto__: null };
	const keys = require_primordials_object.ObjectKeys(obj).sort();
	for (const key of keys) sorted[key] = obj[key];
	return sorted;
}
/**
* Stringify JSON with specific formatting. Applies indentation and line ending
* preferences.
*
* @example
*   ;```ts
*   stringifyWithFormatting({ key: 'value' }, { indent: 4, newline: '\r\n' })
*   // => '{\r\n    "key": "value"\r\n}\r\n'
*   ```
*
* @param content - Object to stringify.
* @param formatting - Formatting preferences (indent and newline)
*
* @returns Formatted JSON string with trailing newline
*/
function stringifyWithFormatting(content, formatting) {
	const { indent, newline } = formatting;
	const format = indent === void 0 || indent === null ? "  " : indent;
	const eol = newline === void 0 || newline === null ? "\n" : newline;
	return `${require_primordials_json.JSONStringify(content, void 0, format)}\n`.replace(/\n/g, eol);
}
/**
* Strip formatting symbols from content object. Removes Symbol.for('indent')
* and Symbol.for('newline') from the object.
*
* @example
*   ;```typescript
*   const obj = { key: 'value', [Symbol.for('indent')]: 2 }
*   stripFormattingSymbols(obj) // { key: "value" }
*   ```
*
* @param content - Content object with potential symbol properties.
*
* @returns Object with symbols removed
*/
function stripFormattingSymbols(content) {
	const { [INDENT_SYMBOL]: _indent, [NEWLINE_SYMBOL]: _newline, ...rest } = content;
	return rest;
}

//#endregion
exports.INDENT_SYMBOL = INDENT_SYMBOL;
exports.NEWLINE_SYMBOL = NEWLINE_SYMBOL;
exports.detectIndent = detectIndent;
exports.detectNewline = detectNewline;
exports.extractFormatting = extractFormatting;
exports.getDefaultFormatting = getDefaultFormatting;
exports.getFormattingFromContent = getFormattingFromContent;
exports.shouldSave = shouldSave;
exports.sortKeys = sortKeys;
exports.stringifyWithFormatting = stringifyWithFormatting;
exports.stripFormattingSymbols = stripFormattingSymbols;