Skip to content

Commit a0eff14

Browse files
Copilotjogibear9988
andcommitted
docs: update documentation for identity mode, preserveFormatting, and removeEmptyRules
- README.md: add identity and removeEmptyRules usage examples, update parse/stringify option docs, update features list - docs/API.md: document preserveFormatting parse option, identity and removeEmptyRules compiler options, update CssStylesheetAST and CssPosition types, add advanced usage examples - docs/AST.md: document offset field on position nodes, document originalSource on stylesheet - docs/EXAMPLES.md: add identity round-trip and removeEmptyRules examples - docs/CHANGELOG.md: add Unreleased section with new features Co-authored-by: jogibear9988 <364896+jogibear9988@users.noreply.github.com>
1 parent 97e7d9a commit a0eff14

File tree

5 files changed

+131
-5
lines changed

5 files changed

+131
-5
lines changed

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ const formatted = stringify(ast, { indent: ' ' })
3232
// Minify output
3333
const minified = stringify(ast, { compress: true })
3434
// => "body{font-size:12px}"
35+
36+
// Identity mode: round-trip CSS exactly as written
37+
const original = 'body { font-size: 12px; }'
38+
const ast2 = parse(original, { preserveFormatting: true })
39+
stringify(ast2, { identity: true }) === original // true
40+
41+
// Remove empty rules
42+
const ast3 = parse('.empty {} .keep { color: red; }')
43+
stringify(ast3, { removeEmptyRules: true })
44+
// => ".keep {\n color: red;\n}"
3545
```
3646

3747
## API
@@ -45,6 +55,7 @@ Parses CSS code and returns an Abstract Syntax Tree (AST).
4555
- `options` (object, optional) - Parsing options
4656
- `silent` (boolean) - Silently fail on parse errors instead of throwing
4757
- `source` (string) - File path for better error reporting
58+
- `preserveFormatting` (boolean) - Store source offsets and original CSS text for identity round-trip (default: `false`)
4859

4960
**Returns:** `CssStylesheetAST` - The parsed CSS as an AST
5061

@@ -57,6 +68,8 @@ Converts a CSS AST back to CSS string with configurable formatting.
5768
- `options` (object, optional) - Stringification options
5869
- `indent` (string) - Indentation string (default: `' '`)
5970
- `compress` (boolean) - Whether to compress/minify the output (default: `false`)
71+
- `identity` (boolean) - Reproduce the original CSS exactly as parsed; requires `preserveFormatting` during parsing (default: `false`)
72+
- `removeEmptyRules` (boolean) - Remove rules with empty declaration blocks (default: `false`)
6073

6174
**Returns:** `string` - The formatted CSS string
6275

@@ -65,7 +78,9 @@ Converts a CSS AST back to CSS string with configurable formatting.
6578
- **Complete CSS Support**: All standard CSS features including selectors, properties, values, at-rules, and comments
6679
- **TypeScript Support**: Full type definitions for all AST nodes and functions
6780
- **Error Handling**: Configurable error handling with detailed position information
68-
- **Formatting Options**: Pretty print, minify, or custom formatting
81+
- **Formatting Options**: Pretty print, minify, identity (round-trip), or custom formatting
82+
- **Identity Round-Trip**: Parse and stringify CSS back to the exact original formatting
83+
- **Empty Rule Removal**: Optionally strip rules with empty declaration blocks
6984
- **Performance Optimized**: Efficient parsing and stringification for large CSS files
7085
- **Source Maps**: Track original source positions for debugging and tooling
7186

docs/API.md

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Parses CSS code and returns an Abstract Syntax Tree (AST).
2222
- `options` (object, optional) - Parsing options
2323
- `silent` (boolean) - Silently fail on parse errors instead of throwing. When `true`, errors are collected in `ast.stylesheet.parsingErrors`
2424
- `source` (string) - File path for better error reporting
25+
- `preserveFormatting` (boolean) - Store source character offsets and original CSS text on the AST for identity round-trip. When `true`, position nodes include an `offset` field and `ast.stylesheet.originalSource` is set. Default: `false`
2526

2627
#### Returns
2728

@@ -53,6 +54,8 @@ Converts a CSS AST back to CSS string with configurable formatting.
5354
- `options` (CompilerOptions, optional) - Stringification options
5455
- `indent` (string) - Indentation string (default: `' '`)
5556
- `compress` (boolean) - Whether to compress/minify the output (default: `false`)
57+
- `identity` (boolean) - Reproduce the original CSS exactly as parsed. Requires `preserveFormatting: true` during parsing. Falls back to beautified output when original source is not available. Default: `false`
58+
- `removeEmptyRules` (boolean) - Remove rules with empty declaration blocks from the output. Works in all modes (beautified, compressed, identity). Default: `false`
5659

5760
#### Returns
5861

@@ -94,6 +97,7 @@ type CssStylesheetAST = {
9497
source?: string;
9598
rules: CssRuleAST[];
9699
parsingErrors?: CssParseError[];
100+
originalSource?: string; // Set when preserveFormatting is true
97101
};
98102
};
99103
```
@@ -159,10 +163,12 @@ type CssPosition = {
159163
start: {
160164
line: number;
161165
column: number;
166+
offset?: number; // Set when preserveFormatting is true
162167
};
163168
end: {
164169
line: number;
165170
column: number;
171+
offset?: number; // Set when preserveFormatting is true
166172
};
167173
};
168174
```
@@ -188,8 +194,10 @@ Options for the stringifier.
188194

189195
```typescript
190196
type CompilerOptions = {
191-
indent?: string; // Default: ' '
192-
compress?: boolean; // Default: false
197+
indent?: string; // Default: ' '
198+
compress?: boolean; // Default: false
199+
identity?: boolean; // Default: false
200+
removeEmptyRules?: boolean; // Default: false
193201
};
194202
```
195203

@@ -290,6 +298,49 @@ console.log(compressed);
290298
// Output: .example{color:red;font-size:16px}
291299
```
292300
301+
### Identity Round-Trip
302+
303+
Reproduce the original CSS exactly as it was written, preserving all whitespace, comments, and formatting:
304+
305+
```javascript
306+
import { parse, stringify } from '@adobe/css-tools';
307+
308+
const css = '.example { color: red; font-size:16px }';
309+
310+
// Parse with preserveFormatting to store original source
311+
const ast = parse(css, { preserveFormatting: true });
312+
313+
// Stringify with identity mode to reproduce the original CSS
314+
const output = stringify(ast, { identity: true });
315+
console.log(output === css); // true
316+
```
317+
318+
When `preserveFormatting` was not used during parsing, identity mode falls back to beautified output.
319+
320+
### Removing Empty Rules
321+
322+
Strip rules with empty declaration blocks from the output:
323+
324+
```javascript
325+
import { parse, stringify } from '@adobe/css-tools';
326+
327+
const css = '.empty {} .keep { color: red; }';
328+
const ast = parse(css);
329+
330+
// Beautified without empty rules
331+
const output = stringify(ast, { removeEmptyRules: true });
332+
console.log(output);
333+
// Output:
334+
// .keep {
335+
// color: red;
336+
// }
337+
338+
// Also works with compressed mode
339+
const compressed = stringify(ast, { compress: true, removeEmptyRules: true });
340+
console.log(compressed);
341+
// Output: .keep{color:red;}
342+
```
343+
293344
## TypeScript Integration
294345
295346
The library provides comprehensive TypeScript support with full type definitions for all AST nodes and functions:

docs/AST.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ Position information for the node in the source code:
1818

1919
```typescript
2020
{
21-
start: { line: number; column: number };
22-
end: { line: number; column: number };
21+
start: { line: number; column: number; offset?: number };
22+
end: { line: number; column: number; offset?: number };
2323
source?: string;
2424
}
2525
```
2626

27+
The `offset` field is a character offset into the original source string, present when `preserveFormatting: true` is used during parsing.
28+
2729
### `parent` (optional)
2830

2931
Reference to the parent node in the AST.
@@ -38,6 +40,7 @@ The root node representing an entire CSS document.
3840
- `stylesheet.source` (optional): Source file path
3941
- `stylesheet.rules`: Array of top-level rules
4042
- `stylesheet.parsingErrors` (optional): Array of parse errors when `silent` option is used
43+
- `stylesheet.originalSource` (optional): The original CSS source string, present when `preserveFormatting: true` is used during parsing
4144

4245
**Example:**
4346
```json

docs/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
- Add `preserveFormatting` parser option to store source character offsets and original CSS text on the AST
12+
- Add `identity` compiler option to reproduce original CSS exactly as parsed (round-trip fidelity)
13+
- Add `removeEmptyRules` compiler option to strip rules with empty declaration blocks
14+
- Add optional `offset` field to position `start`/`end` for source reconstruction
15+
- Add `originalSource` field to `CssStylesheetAST` for identity mode
16+
- Export `CompilerOptions` and `ParseOptions` types from the public API
17+
818
## [4.4.4] - 2025-07-22
919

1020
### Changed

docs/EXAMPLES.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,53 @@ console.log(formatted);
245245
// }
246246
```
247247
248+
### Identity Round-Trip
249+
250+
Reproduce the original CSS exactly as it was written, preserving all whitespace,
251+
comments, and formatting:
252+
253+
```javascript
254+
import { parse, stringify } from '@adobe/css-tools';
255+
256+
const css = `body {
257+
font-size: 12px;
258+
color: #333;
259+
}`;
260+
261+
// Parse with preserveFormatting to store original source
262+
const ast = parse(css, { preserveFormatting: true });
263+
264+
// Stringify with identity mode
265+
const output = stringify(ast, { identity: true });
266+
console.log(output === css); // true — exact round-trip
267+
```
268+
269+
### Removing Empty Rules
270+
271+
```javascript
272+
import { parse, stringify } from '@adobe/css-tools';
273+
274+
const css = `
275+
.unused {}
276+
.active { color: red; }
277+
`;
278+
279+
const ast = parse(css);
280+
281+
// Remove empty rules in beautified output
282+
const output = stringify(ast, { removeEmptyRules: true });
283+
console.log(output);
284+
// Output:
285+
// .active {
286+
// color: red;
287+
// }
288+
289+
// Also works with compressed mode
290+
const compressed = stringify(ast, { compress: true, removeEmptyRules: true });
291+
console.log(compressed);
292+
// Output: .active{color:red;}
293+
```
294+
248295
## Working with Complex CSS
249296
250297
### Nested Rules and At-Rules

0 commit comments

Comments
 (0)