@herb-tools/formatter 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/dist/herb-format.js +447 -227
- package/dist/herb-format.js.map +1 -1
- package/dist/index.cjs +372 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +372 -176
- package/dist/index.esm.js.map +1 -1
- package/dist/types/format-helpers.d.ts +0 -3
- package/dist/types/format-ignore.d.ts +9 -0
- package/dist/types/format-printer.d.ts +23 -0
- package/package.json +5 -5
- package/src/format-helpers.ts +0 -11
- package/src/format-ignore.ts +45 -0
- package/src/format-printer.ts +339 -170
- package/src/formatter.ts +2 -1
|
@@ -29,9 +29,6 @@ export declare const FORMATTABLE_ATTRIBUTES: Record<string, string[]>;
|
|
|
29
29
|
export declare const INLINE_ELEMENTS: Set<string>;
|
|
30
30
|
export declare const CONTENT_PRESERVING_ELEMENTS: Set<string>;
|
|
31
31
|
export declare const SPACEABLE_CONTAINERS: Set<string>;
|
|
32
|
-
export declare const TIGHT_GROUP_PARENTS: Set<string>;
|
|
33
|
-
export declare const TIGHT_GROUP_CHILDREN: Set<string>;
|
|
34
|
-
export declare const SPACING_THRESHOLD = 3;
|
|
35
32
|
/**
|
|
36
33
|
* Token list attributes that contain space-separated values and benefit from
|
|
37
34
|
* spacing around ERB content for readability
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Node } from "@herb-tools/core";
|
|
2
|
+
/**
|
|
3
|
+
* Check if an ERB content node is a herb:formatter ignore comment
|
|
4
|
+
*/
|
|
5
|
+
export declare function isHerbFormatterIgnoreComment(node: Node): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Check if the document contains a herb:formatter ignore directive anywhere.
|
|
8
|
+
*/
|
|
9
|
+
export declare function hasFormatterIgnoreDirective(node: Node): boolean;
|
|
@@ -24,6 +24,10 @@ export declare class FormatPrinter extends Printer {
|
|
|
24
24
|
private currentAttributeName;
|
|
25
25
|
private elementStack;
|
|
26
26
|
private elementFormattingAnalysis;
|
|
27
|
+
private nodeIsMultiline;
|
|
28
|
+
private stringLineCount;
|
|
29
|
+
private tagGroupsCache;
|
|
30
|
+
private allSingleLineCache;
|
|
27
31
|
source: string;
|
|
28
32
|
constructor(source: string, options: Required<FormatOptions>);
|
|
29
33
|
print(input: Node | ParseResult | Token): string;
|
|
@@ -44,6 +48,10 @@ export declare class FormatPrinter extends Printer {
|
|
|
44
48
|
* Useful for testing what output would be generated without affecting the main output
|
|
45
49
|
*/
|
|
46
50
|
private capture;
|
|
51
|
+
/**
|
|
52
|
+
* Track a boundary node's multiline status by comparing line count before/after rendering.
|
|
53
|
+
*/
|
|
54
|
+
private trackBoundary;
|
|
47
55
|
/**
|
|
48
56
|
* Capture all nodes that would be visited during a callback
|
|
49
57
|
* Returns a flat list of all nodes without generating any output
|
|
@@ -72,6 +80,19 @@ export declare class FormatPrinter extends Printer {
|
|
|
72
80
|
* Extract inline nodes (non-attribute, non-whitespace) from a list of nodes
|
|
73
81
|
*/
|
|
74
82
|
private extractInlineNodes;
|
|
83
|
+
/**
|
|
84
|
+
* Check if a node will render as multiple lines when formatted.
|
|
85
|
+
*/
|
|
86
|
+
private isMultilineElement;
|
|
87
|
+
/**
|
|
88
|
+
* Get a grouping key for a node (tag name for HTML, ERB type for ERB)
|
|
89
|
+
*/
|
|
90
|
+
private getGroupingKey;
|
|
91
|
+
/**
|
|
92
|
+
* Detect groups of consecutive same-tag/same-type single-line elements
|
|
93
|
+
* Returns a map of index -> group info for efficient lookup
|
|
94
|
+
*/
|
|
95
|
+
private detectTagGroups;
|
|
75
96
|
/**
|
|
76
97
|
* Determine if spacing should be added between sibling elements
|
|
77
98
|
*
|
|
@@ -127,6 +148,8 @@ export declare class FormatPrinter extends Printer {
|
|
|
127
148
|
visitHTMLElementBody(body: Node[], element: HTMLElementNode): void;
|
|
128
149
|
/**
|
|
129
150
|
* Visit element children with intelligent spacing logic
|
|
151
|
+
*
|
|
152
|
+
* Tracks line positions and immediately splices blank lines after rendering each child.
|
|
130
153
|
*/
|
|
131
154
|
private visitElementChildren;
|
|
132
155
|
visitHTMLOpenTagNode(node: HTMLOpenTagNode): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herb-tools/formatter",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Auto-formatter for HTML+ERB templates with intelligent indentation, line wrapping, and ERB-aware pretty-printing.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://herb-tools.dev",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@herb-tools/config": "0.8.
|
|
39
|
-
"@herb-tools/core": "0.8.
|
|
40
|
-
"@herb-tools/printer": "0.8.
|
|
41
|
-
"@herb-tools/rewriter": "0.8.
|
|
38
|
+
"@herb-tools/config": "0.8.3",
|
|
39
|
+
"@herb-tools/core": "0.8.3",
|
|
40
|
+
"@herb-tools/printer": "0.8.3",
|
|
41
|
+
"@herb-tools/rewriter": "0.8.3"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"package.json",
|
package/src/format-helpers.ts
CHANGED
|
@@ -56,17 +56,6 @@ export const SPACEABLE_CONTAINERS = new Set([
|
|
|
56
56
|
'figure', 'details', 'summary', 'dialog', 'fieldset'
|
|
57
57
|
])
|
|
58
58
|
|
|
59
|
-
export const TIGHT_GROUP_PARENTS = new Set([
|
|
60
|
-
'ul', 'ol', 'nav', 'select', 'datalist', 'optgroup', 'tr', 'thead',
|
|
61
|
-
'tbody', 'tfoot'
|
|
62
|
-
])
|
|
63
|
-
|
|
64
|
-
export const TIGHT_GROUP_CHILDREN = new Set([
|
|
65
|
-
'li', 'option', 'td', 'th', 'dt', 'dd'
|
|
66
|
-
])
|
|
67
|
-
|
|
68
|
-
export const SPACING_THRESHOLD = 3
|
|
69
|
-
|
|
70
59
|
/**
|
|
71
60
|
* Token list attributes that contain space-separated values and benefit from
|
|
72
61
|
* spacing around ERB content for readability
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isERBCommentNode } from "@herb-tools/core"
|
|
2
|
+
import { Visitor } from "@herb-tools/core"
|
|
3
|
+
|
|
4
|
+
import type { Node, ERBContentNode } from "@herb-tools/core"
|
|
5
|
+
|
|
6
|
+
const HERB_FORMATTER_PREFIX = "herb:formatter"
|
|
7
|
+
const HERB_FORMATTER_IGNORE_PREFIX = `${HERB_FORMATTER_PREFIX} ignore`
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if an ERB content node is a herb:formatter ignore comment
|
|
11
|
+
*/
|
|
12
|
+
export function isHerbFormatterIgnoreComment(node: Node): boolean {
|
|
13
|
+
if (!isERBCommentNode(node)) return false
|
|
14
|
+
|
|
15
|
+
const content = node?.content?.value || ""
|
|
16
|
+
|
|
17
|
+
return content.trim() === HERB_FORMATTER_IGNORE_PREFIX
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Check if the document contains a herb:formatter ignore directive anywhere.
|
|
22
|
+
*/
|
|
23
|
+
export function hasFormatterIgnoreDirective(node: Node): boolean {
|
|
24
|
+
const detector = new FormatterIgnoreDetector()
|
|
25
|
+
detector.visit(node)
|
|
26
|
+
return detector.hasIgnoreDirective
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Visitor that detects if the AST contains a herb:formatter ignore directive.
|
|
31
|
+
*/
|
|
32
|
+
class FormatterIgnoreDetector extends Visitor {
|
|
33
|
+
public hasIgnoreDirective = false
|
|
34
|
+
|
|
35
|
+
visitERBContentNode(node: ERBContentNode): void {
|
|
36
|
+
if (isHerbFormatterIgnoreComment(node)) {
|
|
37
|
+
this.hasIgnoreDirective = true
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (this.hasIgnoreDirective) return
|
|
42
|
+
|
|
43
|
+
this.visitChildNodes(node)
|
|
44
|
+
}
|
|
45
|
+
}
|