@herb-tools/formatter 0.8.0 → 0.8.2
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 +403 -193
- package/dist/herb-format.js.map +1 -1
- package/dist/index.cjs +382 -181
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +382 -181
- 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 +3 -12
- package/src/format-ignore.ts +45 -0
- package/src/format-printer.ts +346 -174
- package/src/formatter.ts +2 -1
package/dist/index.cjs
CHANGED
|
@@ -243,7 +243,7 @@ class Token {
|
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
246
|
-
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.
|
|
246
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.2/templates/javascript/packages/core/src/errors.ts.erb
|
|
247
247
|
class HerbError {
|
|
248
248
|
type;
|
|
249
249
|
message;
|
|
@@ -773,7 +773,7 @@ function convertToUTF8(string) {
|
|
|
773
773
|
}
|
|
774
774
|
|
|
775
775
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
776
|
-
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.
|
|
776
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.2/templates/javascript/packages/core/src/nodes.ts.erb
|
|
777
777
|
class Node {
|
|
778
778
|
type;
|
|
779
779
|
location;
|
|
@@ -3007,7 +3007,7 @@ class ParseResult extends Result {
|
|
|
3007
3007
|
}
|
|
3008
3008
|
|
|
3009
3009
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
3010
|
-
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.
|
|
3010
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.2/templates/javascript/packages/core/src/node-type-guards.ts.erb
|
|
3011
3011
|
/**
|
|
3012
3012
|
* Type guard functions for AST nodes.
|
|
3013
3013
|
* These functions provide type checking by combining both instanceof
|
|
@@ -3398,6 +3398,16 @@ function isERBOutputNode(node) {
|
|
|
3398
3398
|
return false;
|
|
3399
3399
|
return ["<%=", "<%=="].includes(node.tag_opening?.value);
|
|
3400
3400
|
}
|
|
3401
|
+
/**
|
|
3402
|
+
* Checks if a node is a ERB comment node (control flow: <%# %>)
|
|
3403
|
+
*/
|
|
3404
|
+
function isERBCommentNode(node) {
|
|
3405
|
+
if (!isERBNode(node))
|
|
3406
|
+
return false;
|
|
3407
|
+
if (!node.tag_opening?.value)
|
|
3408
|
+
return false;
|
|
3409
|
+
return node.tag_opening?.value === "<%#" || (node.tag_opening?.value !== "<%#" && (node.content?.value || "").trimStart().startsWith("#"));
|
|
3410
|
+
}
|
|
3401
3411
|
/**
|
|
3402
3412
|
* Checks if a node is a non-output ERB node (control flow: <% %>)
|
|
3403
3413
|
*/
|
|
@@ -3452,7 +3462,7 @@ function getTagName(node) {
|
|
|
3452
3462
|
* Check if a node is a comment (HTML comment or ERB comment)
|
|
3453
3463
|
*/
|
|
3454
3464
|
function isCommentNode(node) {
|
|
3455
|
-
return
|
|
3465
|
+
return isHTMLCommentNode(node) || isERBCommentNode(node);
|
|
3456
3466
|
}
|
|
3457
3467
|
/**
|
|
3458
3468
|
* Compares two positions to determine if the first comes before the second
|
|
@@ -3494,7 +3504,7 @@ function getNodesAfterPosition(nodes, position, inclusive = true) {
|
|
|
3494
3504
|
}
|
|
3495
3505
|
|
|
3496
3506
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
3497
|
-
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.
|
|
3507
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.8.2/templates/javascript/packages/core/src/visitor.ts.erb
|
|
3498
3508
|
class Visitor {
|
|
3499
3509
|
visit(node) {
|
|
3500
3510
|
if (!node)
|
|
@@ -4121,14 +4131,6 @@ const SPACEABLE_CONTAINERS = new Set([
|
|
|
4121
4131
|
'div', 'section', 'article', 'main', 'header', 'footer', 'aside',
|
|
4122
4132
|
'figure', 'details', 'summary', 'dialog', 'fieldset'
|
|
4123
4133
|
]);
|
|
4124
|
-
const TIGHT_GROUP_PARENTS = new Set([
|
|
4125
|
-
'ul', 'ol', 'nav', 'select', 'datalist', 'optgroup', 'tr', 'thead',
|
|
4126
|
-
'tbody', 'tfoot'
|
|
4127
|
-
]);
|
|
4128
|
-
const TIGHT_GROUP_CHILDREN = new Set([
|
|
4129
|
-
'li', 'option', 'td', 'th', 'dt', 'dd'
|
|
4130
|
-
]);
|
|
4131
|
-
const SPACING_THRESHOLD = 3;
|
|
4132
4134
|
/**
|
|
4133
4135
|
* Token list attributes that contain space-separated values and benefit from
|
|
4134
4136
|
* spacing around ERB content for readability
|
|
@@ -4232,7 +4234,8 @@ function lineEndsWithOpeningPunctuation(line) {
|
|
|
4232
4234
|
* Check if a string ends with an ERB tag
|
|
4233
4235
|
*/
|
|
4234
4236
|
function endsWithERBTag(text) {
|
|
4235
|
-
|
|
4237
|
+
const trimmed = text.trim();
|
|
4238
|
+
return /%>$/.test(trimmed) || /%>\S+$/.test(trimmed);
|
|
4236
4239
|
}
|
|
4237
4240
|
/**
|
|
4238
4241
|
* Check if a string starts with an ERB tag
|
|
@@ -4514,6 +4517,10 @@ class FormatPrinter extends Printer {
|
|
|
4514
4517
|
currentAttributeName = null;
|
|
4515
4518
|
elementStack = [];
|
|
4516
4519
|
elementFormattingAnalysis = new Map();
|
|
4520
|
+
nodeIsMultiline = new Map();
|
|
4521
|
+
stringLineCount = 0;
|
|
4522
|
+
tagGroupsCache = new Map();
|
|
4523
|
+
allSingleLineCache = new Map();
|
|
4517
4524
|
source;
|
|
4518
4525
|
constructor(source, options) {
|
|
4519
4526
|
super();
|
|
@@ -4528,6 +4535,10 @@ class FormatPrinter extends Printer {
|
|
|
4528
4535
|
// TODO: refactor to use @herb-tools/printer infrastructre (or rework printer use push and this.lines)
|
|
4529
4536
|
this.lines = [];
|
|
4530
4537
|
this.indentLevel = 0;
|
|
4538
|
+
this.stringLineCount = 0;
|
|
4539
|
+
this.nodeIsMultiline.clear();
|
|
4540
|
+
this.tagGroupsCache.clear();
|
|
4541
|
+
this.allSingleLineCache.clear();
|
|
4531
4542
|
this.visit(node);
|
|
4532
4543
|
return this.lines.join("\n");
|
|
4533
4544
|
}
|
|
@@ -4561,7 +4572,9 @@ class FormatPrinter extends Printer {
|
|
|
4561
4572
|
capture(callback) {
|
|
4562
4573
|
const previousLines = this.lines;
|
|
4563
4574
|
const previousInlineMode = this.inlineMode;
|
|
4575
|
+
const previousStringLineCount = this.stringLineCount;
|
|
4564
4576
|
this.lines = [];
|
|
4577
|
+
this.stringLineCount = 0;
|
|
4565
4578
|
try {
|
|
4566
4579
|
callback();
|
|
4567
4580
|
return this.lines;
|
|
@@ -4569,8 +4582,18 @@ class FormatPrinter extends Printer {
|
|
|
4569
4582
|
finally {
|
|
4570
4583
|
this.lines = previousLines;
|
|
4571
4584
|
this.inlineMode = previousInlineMode;
|
|
4585
|
+
this.stringLineCount = previousStringLineCount;
|
|
4572
4586
|
}
|
|
4573
4587
|
}
|
|
4588
|
+
/**
|
|
4589
|
+
* Track a boundary node's multiline status by comparing line count before/after rendering.
|
|
4590
|
+
*/
|
|
4591
|
+
trackBoundary(node, callback) {
|
|
4592
|
+
const startLineCount = this.stringLineCount;
|
|
4593
|
+
callback();
|
|
4594
|
+
const endLineCount = this.stringLineCount;
|
|
4595
|
+
this.nodeIsMultiline.set(node, (endLineCount - startLineCount) > 1);
|
|
4596
|
+
}
|
|
4574
4597
|
/**
|
|
4575
4598
|
* Capture all nodes that would be visited during a callback
|
|
4576
4599
|
* Returns a flat list of all nodes without generating any output
|
|
@@ -4606,6 +4629,7 @@ class FormatPrinter extends Printer {
|
|
|
4606
4629
|
*/
|
|
4607
4630
|
push(line) {
|
|
4608
4631
|
this.lines.push(line);
|
|
4632
|
+
this.stringLineCount++;
|
|
4609
4633
|
}
|
|
4610
4634
|
/**
|
|
4611
4635
|
* @deprecated refactor to use @herb-tools/printer infrastructre (or rework printer use push and this.lines)
|
|
@@ -4650,6 +4674,79 @@ class FormatPrinter extends Printer {
|
|
|
4650
4674
|
extractInlineNodes(nodes) {
|
|
4651
4675
|
return nodes.filter(child => isNoneOf(child, HTMLAttributeNode, WhitespaceNode));
|
|
4652
4676
|
}
|
|
4677
|
+
/**
|
|
4678
|
+
* Check if a node will render as multiple lines when formatted.
|
|
4679
|
+
*/
|
|
4680
|
+
isMultilineElement(node) {
|
|
4681
|
+
if (isNode(node, ERBContentNode)) {
|
|
4682
|
+
return (node.content?.value || "").includes("\n");
|
|
4683
|
+
}
|
|
4684
|
+
if (isNode(node, HTMLElementNode) && isContentPreserving(node)) {
|
|
4685
|
+
return true;
|
|
4686
|
+
}
|
|
4687
|
+
const tracked = this.nodeIsMultiline.get(node);
|
|
4688
|
+
if (tracked !== undefined) {
|
|
4689
|
+
return tracked;
|
|
4690
|
+
}
|
|
4691
|
+
return false;
|
|
4692
|
+
}
|
|
4693
|
+
/**
|
|
4694
|
+
* Get a grouping key for a node (tag name for HTML, ERB type for ERB)
|
|
4695
|
+
*/
|
|
4696
|
+
getGroupingKey(node) {
|
|
4697
|
+
if (isNode(node, HTMLElementNode)) {
|
|
4698
|
+
return getTagName(node);
|
|
4699
|
+
}
|
|
4700
|
+
if (isERBOutputNode(node))
|
|
4701
|
+
return "erb-output";
|
|
4702
|
+
if (isERBCommentNode(node))
|
|
4703
|
+
return "erb-comment";
|
|
4704
|
+
if (isERBNode(node))
|
|
4705
|
+
return "erb-code";
|
|
4706
|
+
return null;
|
|
4707
|
+
}
|
|
4708
|
+
/**
|
|
4709
|
+
* Detect groups of consecutive same-tag/same-type single-line elements
|
|
4710
|
+
* Returns a map of index -> group info for efficient lookup
|
|
4711
|
+
*/
|
|
4712
|
+
detectTagGroups(siblings) {
|
|
4713
|
+
const cached = this.tagGroupsCache.get(siblings);
|
|
4714
|
+
if (cached)
|
|
4715
|
+
return cached;
|
|
4716
|
+
const groupMap = new Map();
|
|
4717
|
+
const meaningfulNodes = [];
|
|
4718
|
+
for (let i = 0; i < siblings.length; i++) {
|
|
4719
|
+
const node = siblings[i];
|
|
4720
|
+
if (!this.isMultilineElement(node)) {
|
|
4721
|
+
const groupKey = this.getGroupingKey(node);
|
|
4722
|
+
if (groupKey) {
|
|
4723
|
+
meaningfulNodes.push({ index: i, groupKey });
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4726
|
+
}
|
|
4727
|
+
let groupStart = 0;
|
|
4728
|
+
while (groupStart < meaningfulNodes.length) {
|
|
4729
|
+
const startGroupKey = meaningfulNodes[groupStart].groupKey;
|
|
4730
|
+
let groupEnd = groupStart;
|
|
4731
|
+
while (groupEnd + 1 < meaningfulNodes.length && meaningfulNodes[groupEnd + 1].groupKey === startGroupKey) {
|
|
4732
|
+
groupEnd++;
|
|
4733
|
+
}
|
|
4734
|
+
if (groupEnd > groupStart) {
|
|
4735
|
+
const groupStartIndex = meaningfulNodes[groupStart].index;
|
|
4736
|
+
const groupEndIndex = meaningfulNodes[groupEnd].index;
|
|
4737
|
+
for (let i = groupStart; i <= groupEnd; i++) {
|
|
4738
|
+
groupMap.set(meaningfulNodes[i].index, {
|
|
4739
|
+
tagName: startGroupKey,
|
|
4740
|
+
groupStart: groupStartIndex,
|
|
4741
|
+
groupEnd: groupEndIndex
|
|
4742
|
+
});
|
|
4743
|
+
}
|
|
4744
|
+
}
|
|
4745
|
+
groupStart = groupEnd + 1;
|
|
4746
|
+
}
|
|
4747
|
+
this.tagGroupsCache.set(siblings, groupMap);
|
|
4748
|
+
return groupMap;
|
|
4749
|
+
}
|
|
4653
4750
|
/**
|
|
4654
4751
|
* Determine if spacing should be added between sibling elements
|
|
4655
4752
|
*
|
|
@@ -4665,48 +4762,59 @@ class FormatPrinter extends Printer {
|
|
|
4665
4762
|
* @param hasExistingSpacing - Whether user-added spacing already exists
|
|
4666
4763
|
* @returns true if spacing should be added before the current element
|
|
4667
4764
|
*/
|
|
4668
|
-
shouldAddSpacingBetweenSiblings(parentElement, siblings, currentIndex
|
|
4669
|
-
|
|
4765
|
+
shouldAddSpacingBetweenSiblings(parentElement, siblings, currentIndex) {
|
|
4766
|
+
const currentNode = siblings[currentIndex];
|
|
4767
|
+
const previousMeaningfulIndex = findPreviousMeaningfulSibling(siblings, currentIndex);
|
|
4768
|
+
const previousNode = previousMeaningfulIndex !== -1 ? siblings[previousMeaningfulIndex] : null;
|
|
4769
|
+
if (previousNode && (isNode(previousNode, XMLDeclarationNode) || isNode(previousNode, HTMLDoctypeNode))) {
|
|
4670
4770
|
return true;
|
|
4671
4771
|
}
|
|
4672
4772
|
const hasMixedContent = siblings.some(child => isNode(child, HTMLTextNode) && child.content.trim() !== "");
|
|
4673
|
-
if (hasMixedContent)
|
|
4773
|
+
if (hasMixedContent)
|
|
4674
4774
|
return false;
|
|
4775
|
+
const isCurrentComment = isCommentNode(currentNode);
|
|
4776
|
+
const isPreviousComment = previousNode ? isCommentNode(previousNode) : false;
|
|
4777
|
+
const isCurrentMultiline = this.isMultilineElement(currentNode);
|
|
4778
|
+
const isPreviousMultiline = previousNode ? this.isMultilineElement(previousNode) : false;
|
|
4779
|
+
if (isPreviousComment && !isCurrentComment && (isNode(currentNode, HTMLElementNode) || isERBNode(currentNode))) {
|
|
4780
|
+
return isPreviousMultiline && isCurrentMultiline;
|
|
4675
4781
|
}
|
|
4676
|
-
|
|
4677
|
-
if (meaningfulSiblings.length < SPACING_THRESHOLD) {
|
|
4782
|
+
if (isPreviousComment && isCurrentComment) {
|
|
4678
4783
|
return false;
|
|
4679
4784
|
}
|
|
4785
|
+
if (isCurrentMultiline || isPreviousMultiline) {
|
|
4786
|
+
return true;
|
|
4787
|
+
}
|
|
4788
|
+
const meaningfulSiblings = siblings.filter(child => isNonWhitespaceNode(child));
|
|
4680
4789
|
const parentTagName = parentElement ? getTagName(parentElement) : null;
|
|
4681
|
-
|
|
4682
|
-
|
|
4790
|
+
const isSpaceableContainer = !parentTagName || SPACEABLE_CONTAINERS.has(parentTagName);
|
|
4791
|
+
const tagGroups = this.detectTagGroups(siblings);
|
|
4792
|
+
const cached = this.allSingleLineCache.get(siblings);
|
|
4793
|
+
let allSingleLineHTMLElements;
|
|
4794
|
+
if (cached !== undefined) {
|
|
4795
|
+
allSingleLineHTMLElements = cached;
|
|
4796
|
+
}
|
|
4797
|
+
else {
|
|
4798
|
+
allSingleLineHTMLElements = meaningfulSiblings.every(node => isNode(node, HTMLElementNode) && !this.isMultilineElement(node));
|
|
4799
|
+
this.allSingleLineCache.set(siblings, allSingleLineHTMLElements);
|
|
4683
4800
|
}
|
|
4684
|
-
const isSpaceableContainer = !parentTagName || (parentTagName && SPACEABLE_CONTAINERS.has(parentTagName));
|
|
4685
4801
|
if (!isSpaceableContainer && meaningfulSiblings.length < 5) {
|
|
4686
4802
|
return false;
|
|
4687
4803
|
}
|
|
4688
|
-
const
|
|
4689
|
-
const
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
return false;
|
|
4699
|
-
}
|
|
4804
|
+
const currentGroup = tagGroups.get(currentIndex);
|
|
4805
|
+
const previousGroup = previousNode ? tagGroups.get(previousMeaningfulIndex) : undefined;
|
|
4806
|
+
if (currentGroup && previousGroup && currentGroup.groupStart === previousGroup.groupStart && currentGroup.groupEnd === previousGroup.groupEnd) {
|
|
4807
|
+
return false;
|
|
4808
|
+
}
|
|
4809
|
+
if (previousGroup && previousGroup.groupEnd === previousMeaningfulIndex) {
|
|
4810
|
+
return true;
|
|
4811
|
+
}
|
|
4812
|
+
if (allSingleLineHTMLElements && tagGroups.size === 0) {
|
|
4813
|
+
return false;
|
|
4700
4814
|
}
|
|
4701
4815
|
if (isNode(currentNode, HTMLElementNode)) {
|
|
4702
4816
|
const currentTagName = getTagName(currentNode);
|
|
4703
|
-
if (INLINE_ELEMENTS.has(currentTagName)) {
|
|
4704
|
-
return false;
|
|
4705
|
-
}
|
|
4706
|
-
if (TIGHT_GROUP_CHILDREN.has(currentTagName)) {
|
|
4707
|
-
return false;
|
|
4708
|
-
}
|
|
4709
|
-
if (currentTagName === 'a' && parentTagName === 'nav') {
|
|
4817
|
+
if (currentTagName && INLINE_ELEMENTS.has(currentTagName)) {
|
|
4710
4818
|
return false;
|
|
4711
4819
|
}
|
|
4712
4820
|
}
|
|
@@ -4927,7 +5035,7 @@ class FormatPrinter extends Printer {
|
|
|
4927
5035
|
this.inlineMode = wasInlineMode;
|
|
4928
5036
|
return;
|
|
4929
5037
|
}
|
|
4930
|
-
let
|
|
5038
|
+
let lastMeaningfulNode = null;
|
|
4931
5039
|
let hasHandledSpacing = false;
|
|
4932
5040
|
for (let i = 0; i < children.length; i++) {
|
|
4933
5041
|
const child = children[i];
|
|
@@ -4941,36 +5049,42 @@ class FormatPrinter extends Printer {
|
|
|
4941
5049
|
}
|
|
4942
5050
|
if (shouldAppendToLastLine(child, children, i)) {
|
|
4943
5051
|
this.appendChildToLastLine(child, children, i);
|
|
4944
|
-
|
|
5052
|
+
lastMeaningfulNode = child;
|
|
4945
5053
|
hasHandledSpacing = false;
|
|
4946
5054
|
continue;
|
|
4947
5055
|
}
|
|
4948
|
-
if (isNonWhitespaceNode(child)
|
|
4949
|
-
|
|
4950
|
-
|
|
5056
|
+
if (!isNonWhitespaceNode(child))
|
|
5057
|
+
continue;
|
|
5058
|
+
const childStartLine = this.stringLineCount;
|
|
4951
5059
|
this.visit(child);
|
|
4952
|
-
if (
|
|
4953
|
-
|
|
4954
|
-
|
|
5060
|
+
if (lastMeaningfulNode && !hasHandledSpacing) {
|
|
5061
|
+
const shouldAddSpacing = this.shouldAddSpacingBetweenSiblings(null, children, i);
|
|
5062
|
+
if (shouldAddSpacing) {
|
|
5063
|
+
this.lines.splice(childStartLine, 0, "");
|
|
5064
|
+
this.stringLineCount++;
|
|
5065
|
+
}
|
|
4955
5066
|
}
|
|
5067
|
+
lastMeaningfulNode = child;
|
|
5068
|
+
hasHandledSpacing = false;
|
|
4956
5069
|
}
|
|
4957
5070
|
}
|
|
4958
5071
|
visitHTMLElementNode(node) {
|
|
4959
5072
|
this.elementStack.push(node);
|
|
4960
5073
|
this.elementFormattingAnalysis.set(node, this.analyzeElementFormatting(node));
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
5074
|
+
this.trackBoundary(node, () => {
|
|
5075
|
+
if (this.inlineMode && node.is_void && this.indentLevel === 0) {
|
|
5076
|
+
const openTag = this.capture(() => this.visit(node.open_tag)).join('');
|
|
5077
|
+
this.pushToLastLine(openTag);
|
|
5078
|
+
return;
|
|
5079
|
+
}
|
|
5080
|
+
this.visit(node.open_tag);
|
|
5081
|
+
if (node.body.length > 0) {
|
|
5082
|
+
this.visitHTMLElementBody(node.body, node);
|
|
5083
|
+
}
|
|
5084
|
+
if (node.close_tag) {
|
|
5085
|
+
this.visit(node.close_tag);
|
|
5086
|
+
}
|
|
5087
|
+
});
|
|
4974
5088
|
this.elementStack.pop();
|
|
4975
5089
|
}
|
|
4976
5090
|
visitHTMLElementBody(body, element) {
|
|
@@ -5117,17 +5231,19 @@ class FormatPrinter extends Printer {
|
|
|
5117
5231
|
}
|
|
5118
5232
|
/**
|
|
5119
5233
|
* Visit element children with intelligent spacing logic
|
|
5234
|
+
*
|
|
5235
|
+
* Tracks line positions and immediately splices blank lines after rendering each child.
|
|
5120
5236
|
*/
|
|
5121
5237
|
visitElementChildren(body, parentElement) {
|
|
5122
|
-
let
|
|
5238
|
+
let lastMeaningfulNode = null;
|
|
5123
5239
|
let hasHandledSpacing = false;
|
|
5124
|
-
for (let
|
|
5125
|
-
const child = body[
|
|
5240
|
+
for (let index = 0; index < body.length; index++) {
|
|
5241
|
+
const child = body[index];
|
|
5126
5242
|
if (isNode(child, HTMLTextNode)) {
|
|
5127
5243
|
const isWhitespaceOnly = child.content.trim() === "";
|
|
5128
5244
|
if (isWhitespaceOnly) {
|
|
5129
|
-
const hasPreviousNonWhitespace =
|
|
5130
|
-
const hasNextNonWhitespace =
|
|
5245
|
+
const hasPreviousNonWhitespace = index > 0 && isNonWhitespaceNode(body[index - 1]);
|
|
5246
|
+
const hasNextNonWhitespace = index < body.length - 1 && isNonWhitespaceNode(body[index + 1]);
|
|
5131
5247
|
const hasMultipleNewlines = child.content.includes('\n\n');
|
|
5132
5248
|
if (hasPreviousNonWhitespace && hasNextNonWhitespace && hasMultipleNewlines) {
|
|
5133
5249
|
this.push("");
|
|
@@ -5136,24 +5252,26 @@ class FormatPrinter extends Printer {
|
|
|
5136
5252
|
continue;
|
|
5137
5253
|
}
|
|
5138
5254
|
}
|
|
5139
|
-
if (isNonWhitespaceNode(child)
|
|
5140
|
-
|
|
5141
|
-
const hasExistingSpacing = i > 0 && isNode(element, HTMLTextNode) && element.content.trim() === "" && (element.content.includes('\n\n') || element.content.split('\n').length > 2);
|
|
5142
|
-
const shouldAddSpacing = this.shouldAddSpacingBetweenSiblings(parentElement, body, i, hasExistingSpacing);
|
|
5143
|
-
if (shouldAddSpacing) {
|
|
5144
|
-
this.push("");
|
|
5145
|
-
}
|
|
5146
|
-
}
|
|
5255
|
+
if (!isNonWhitespaceNode(child))
|
|
5256
|
+
continue;
|
|
5147
5257
|
let hasTrailingHerbDisable = false;
|
|
5148
5258
|
if (isNode(child, HTMLElementNode) && child.close_tag) {
|
|
5149
|
-
for (let j =
|
|
5259
|
+
for (let j = index + 1; j < body.length; j++) {
|
|
5150
5260
|
const nextChild = body[j];
|
|
5151
5261
|
if (isNode(nextChild, WhitespaceNode) || isPureWhitespaceNode(nextChild)) {
|
|
5152
5262
|
continue;
|
|
5153
5263
|
}
|
|
5154
5264
|
if (isNode(nextChild, ERBContentNode) && isHerbDisableComment(nextChild)) {
|
|
5155
5265
|
hasTrailingHerbDisable = true;
|
|
5266
|
+
const childStartLine = this.stringLineCount;
|
|
5156
5267
|
this.visit(child);
|
|
5268
|
+
if (lastMeaningfulNode && !hasHandledSpacing) {
|
|
5269
|
+
const shouldAddSpacing = this.shouldAddSpacingBetweenSiblings(parentElement, body, index);
|
|
5270
|
+
if (shouldAddSpacing) {
|
|
5271
|
+
this.lines.splice(childStartLine, 0, "");
|
|
5272
|
+
this.stringLineCount++;
|
|
5273
|
+
}
|
|
5274
|
+
}
|
|
5157
5275
|
const herbDisableString = this.capture(() => {
|
|
5158
5276
|
const savedIndentLevel = this.indentLevel;
|
|
5159
5277
|
this.indentLevel = 0;
|
|
@@ -5163,17 +5281,25 @@ class FormatPrinter extends Printer {
|
|
|
5163
5281
|
this.indentLevel = savedIndentLevel;
|
|
5164
5282
|
}).join("");
|
|
5165
5283
|
this.pushToLastLine(' ' + herbDisableString);
|
|
5166
|
-
|
|
5284
|
+
index = j;
|
|
5285
|
+
lastMeaningfulNode = child;
|
|
5286
|
+
hasHandledSpacing = false;
|
|
5167
5287
|
break;
|
|
5168
5288
|
}
|
|
5169
5289
|
break;
|
|
5170
5290
|
}
|
|
5171
5291
|
}
|
|
5172
5292
|
if (!hasTrailingHerbDisable) {
|
|
5293
|
+
const childStartLine = this.stringLineCount;
|
|
5173
5294
|
this.visit(child);
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5295
|
+
if (lastMeaningfulNode && !hasHandledSpacing) {
|
|
5296
|
+
const shouldAddSpacing = this.shouldAddSpacingBetweenSiblings(parentElement, body, index);
|
|
5297
|
+
if (shouldAddSpacing) {
|
|
5298
|
+
this.lines.splice(childStartLine, 0, "");
|
|
5299
|
+
this.stringLineCount++;
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5302
|
+
lastMeaningfulNode = child;
|
|
5177
5303
|
hasHandledSpacing = false;
|
|
5178
5304
|
}
|
|
5179
5305
|
}
|
|
@@ -5269,6 +5395,11 @@ class FormatPrinter extends Printer {
|
|
|
5269
5395
|
return "";
|
|
5270
5396
|
}
|
|
5271
5397
|
}).join("");
|
|
5398
|
+
const trimmedInner = inner.trim();
|
|
5399
|
+
if (trimmedInner.startsWith('[if ') && trimmedInner.endsWith('<![endif]')) {
|
|
5400
|
+
this.pushWithIndent(open + inner + close);
|
|
5401
|
+
return;
|
|
5402
|
+
}
|
|
5272
5403
|
const hasNewlines = inner.includes('\n');
|
|
5273
5404
|
if (hasNewlines) {
|
|
5274
5405
|
const lines = inner.split('\n');
|
|
@@ -5351,8 +5482,7 @@ class FormatPrinter extends Printer {
|
|
|
5351
5482
|
this.pushWithIndent(IdentityPrinter.print(node));
|
|
5352
5483
|
}
|
|
5353
5484
|
visitERBContentNode(node) {
|
|
5354
|
-
|
|
5355
|
-
if (node.tag_opening?.value === "<%#") {
|
|
5485
|
+
if (isERBCommentNode(node)) {
|
|
5356
5486
|
this.visitERBCommentNode(node);
|
|
5357
5487
|
}
|
|
5358
5488
|
else {
|
|
@@ -5363,83 +5493,92 @@ class FormatPrinter extends Printer {
|
|
|
5363
5493
|
this.printERBNode(node);
|
|
5364
5494
|
}
|
|
5365
5495
|
visitERBYieldNode(node) {
|
|
5366
|
-
this.
|
|
5496
|
+
this.trackBoundary(node, () => {
|
|
5497
|
+
this.printERBNode(node);
|
|
5498
|
+
});
|
|
5367
5499
|
}
|
|
5368
5500
|
visitERBInNode(node) {
|
|
5369
|
-
this.
|
|
5370
|
-
|
|
5501
|
+
this.trackBoundary(node, () => {
|
|
5502
|
+
this.printERBNode(node);
|
|
5503
|
+
this.withIndent(() => this.visitAll(node.statements));
|
|
5504
|
+
});
|
|
5371
5505
|
}
|
|
5372
5506
|
visitERBCaseMatchNode(node) {
|
|
5373
|
-
this.
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
visitERBBlockNode(node) {
|
|
5382
|
-
this.printERBNode(node);
|
|
5383
|
-
this.withIndent(() => {
|
|
5384
|
-
const hasTextFlow = this.isInTextFlowContext(null, node.body);
|
|
5385
|
-
if (hasTextFlow) {
|
|
5386
|
-
this.visitTextFlowChildren(node.body);
|
|
5387
|
-
}
|
|
5388
|
-
else {
|
|
5389
|
-
this.visitElementChildren(node.body, null);
|
|
5390
|
-
}
|
|
5507
|
+
this.trackBoundary(node, () => {
|
|
5508
|
+
this.printERBNode(node);
|
|
5509
|
+
this.withIndent(() => this.visitAll(node.children));
|
|
5510
|
+
this.visitAll(node.conditions);
|
|
5511
|
+
if (node.else_clause)
|
|
5512
|
+
this.visit(node.else_clause);
|
|
5513
|
+
if (node.end_node)
|
|
5514
|
+
this.visit(node.end_node);
|
|
5391
5515
|
});
|
|
5392
|
-
if (node.end_node)
|
|
5393
|
-
this.visit(node.end_node);
|
|
5394
5516
|
}
|
|
5395
|
-
|
|
5396
|
-
|
|
5517
|
+
visitERBBlockNode(node) {
|
|
5518
|
+
this.trackBoundary(node, () => {
|
|
5397
5519
|
this.printERBNode(node);
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
this.
|
|
5520
|
+
this.withIndent(() => {
|
|
5521
|
+
const hasTextFlow = this.isInTextFlowContext(null, node.body);
|
|
5522
|
+
if (hasTextFlow) {
|
|
5523
|
+
this.visitTextFlowChildren(node.body);
|
|
5402
5524
|
}
|
|
5403
5525
|
else {
|
|
5404
|
-
|
|
5405
|
-
|
|
5526
|
+
this.visitElementChildren(node.body, null);
|
|
5527
|
+
}
|
|
5528
|
+
});
|
|
5529
|
+
if (node.end_node)
|
|
5530
|
+
this.visit(node.end_node);
|
|
5531
|
+
});
|
|
5532
|
+
}
|
|
5533
|
+
visitERBIfNode(node) {
|
|
5534
|
+
this.trackBoundary(node, () => {
|
|
5535
|
+
if (this.inlineMode) {
|
|
5536
|
+
this.printERBNode(node);
|
|
5537
|
+
node.statements.forEach(child => {
|
|
5538
|
+
if (isNode(child, HTMLAttributeNode)) {
|
|
5406
5539
|
this.lines.push(" ");
|
|
5540
|
+
this.lines.push(this.renderAttribute(child));
|
|
5407
5541
|
}
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5542
|
+
else {
|
|
5543
|
+
const shouldAddSpaces = this.isInTokenListAttribute;
|
|
5544
|
+
if (shouldAddSpaces) {
|
|
5545
|
+
this.lines.push(" ");
|
|
5546
|
+
}
|
|
5547
|
+
this.visit(child);
|
|
5548
|
+
if (shouldAddSpaces) {
|
|
5549
|
+
this.lines.push(" ");
|
|
5550
|
+
}
|
|
5411
5551
|
}
|
|
5552
|
+
});
|
|
5553
|
+
const hasHTMLAttributes = node.statements.some(child => isNode(child, HTMLAttributeNode));
|
|
5554
|
+
const isTokenList = this.isInTokenListAttribute;
|
|
5555
|
+
if ((hasHTMLAttributes || isTokenList) && node.end_node) {
|
|
5556
|
+
this.lines.push(" ");
|
|
5412
5557
|
}
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
this.lines.push(" ");
|
|
5558
|
+
if (node.subsequent)
|
|
5559
|
+
this.visit(node.subsequent);
|
|
5560
|
+
if (node.end_node)
|
|
5561
|
+
this.visit(node.end_node);
|
|
5418
5562
|
}
|
|
5419
|
-
|
|
5420
|
-
this.
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
}
|
|
5429
|
-
|
|
5430
|
-
this.visit(node.subsequent);
|
|
5431
|
-
if (node.end_node)
|
|
5432
|
-
this.visit(node.end_node);
|
|
5433
|
-
}
|
|
5563
|
+
else {
|
|
5564
|
+
this.printERBNode(node);
|
|
5565
|
+
this.withIndent(() => {
|
|
5566
|
+
node.statements.forEach(child => this.visit(child));
|
|
5567
|
+
});
|
|
5568
|
+
if (node.subsequent)
|
|
5569
|
+
this.visit(node.subsequent);
|
|
5570
|
+
if (node.end_node)
|
|
5571
|
+
this.visit(node.end_node);
|
|
5572
|
+
}
|
|
5573
|
+
});
|
|
5434
5574
|
}
|
|
5435
5575
|
visitERBElseNode(node) {
|
|
5576
|
+
this.printERBNode(node);
|
|
5436
5577
|
if (this.inlineMode) {
|
|
5437
|
-
this.
|
|
5438
|
-
node.statements.forEach(statement => this.visit(statement));
|
|
5578
|
+
this.visitAll(node.statements);
|
|
5439
5579
|
}
|
|
5440
5580
|
else {
|
|
5441
|
-
this.
|
|
5442
|
-
this.withIndent(() => node.statements.forEach(statement => this.visit(statement)));
|
|
5581
|
+
this.withIndent(() => this.visitAll(node.statements));
|
|
5443
5582
|
}
|
|
5444
5583
|
}
|
|
5445
5584
|
visitERBWhenNode(node) {
|
|
@@ -5447,43 +5586,53 @@ class FormatPrinter extends Printer {
|
|
|
5447
5586
|
this.withIndent(() => this.visitAll(node.statements));
|
|
5448
5587
|
}
|
|
5449
5588
|
visitERBCaseNode(node) {
|
|
5450
|
-
this.
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5589
|
+
this.trackBoundary(node, () => {
|
|
5590
|
+
this.printERBNode(node);
|
|
5591
|
+
this.withIndent(() => this.visitAll(node.children));
|
|
5592
|
+
this.visitAll(node.conditions);
|
|
5593
|
+
if (node.else_clause)
|
|
5594
|
+
this.visit(node.else_clause);
|
|
5595
|
+
if (node.end_node)
|
|
5596
|
+
this.visit(node.end_node);
|
|
5597
|
+
});
|
|
5457
5598
|
}
|
|
5458
5599
|
visitERBBeginNode(node) {
|
|
5459
|
-
this.
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5600
|
+
this.trackBoundary(node, () => {
|
|
5601
|
+
this.printERBNode(node);
|
|
5602
|
+
this.withIndent(() => this.visitAll(node.statements));
|
|
5603
|
+
if (node.rescue_clause)
|
|
5604
|
+
this.visit(node.rescue_clause);
|
|
5605
|
+
if (node.else_clause)
|
|
5606
|
+
this.visit(node.else_clause);
|
|
5607
|
+
if (node.ensure_clause)
|
|
5608
|
+
this.visit(node.ensure_clause);
|
|
5609
|
+
if (node.end_node)
|
|
5610
|
+
this.visit(node.end_node);
|
|
5611
|
+
});
|
|
5469
5612
|
}
|
|
5470
5613
|
visitERBWhileNode(node) {
|
|
5471
|
-
this.
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5614
|
+
this.trackBoundary(node, () => {
|
|
5615
|
+
this.printERBNode(node);
|
|
5616
|
+
this.withIndent(() => this.visitAll(node.statements));
|
|
5617
|
+
if (node.end_node)
|
|
5618
|
+
this.visit(node.end_node);
|
|
5619
|
+
});
|
|
5475
5620
|
}
|
|
5476
5621
|
visitERBUntilNode(node) {
|
|
5477
|
-
this.
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5622
|
+
this.trackBoundary(node, () => {
|
|
5623
|
+
this.printERBNode(node);
|
|
5624
|
+
this.withIndent(() => this.visitAll(node.statements));
|
|
5625
|
+
if (node.end_node)
|
|
5626
|
+
this.visit(node.end_node);
|
|
5627
|
+
});
|
|
5481
5628
|
}
|
|
5482
5629
|
visitERBForNode(node) {
|
|
5483
|
-
this.
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5630
|
+
this.trackBoundary(node, () => {
|
|
5631
|
+
this.printERBNode(node);
|
|
5632
|
+
this.withIndent(() => this.visitAll(node.statements));
|
|
5633
|
+
if (node.end_node)
|
|
5634
|
+
this.visit(node.end_node);
|
|
5635
|
+
});
|
|
5487
5636
|
}
|
|
5488
5637
|
visitERBRescueNode(node) {
|
|
5489
5638
|
this.printERBNode(node);
|
|
@@ -5494,12 +5643,14 @@ class FormatPrinter extends Printer {
|
|
|
5494
5643
|
this.withIndent(() => this.visitAll(node.statements));
|
|
5495
5644
|
}
|
|
5496
5645
|
visitERBUnlessNode(node) {
|
|
5497
|
-
this.
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5646
|
+
this.trackBoundary(node, () => {
|
|
5647
|
+
this.printERBNode(node);
|
|
5648
|
+
this.withIndent(() => this.visitAll(node.statements));
|
|
5649
|
+
if (node.else_clause)
|
|
5650
|
+
this.visit(node.else_clause);
|
|
5651
|
+
if (node.end_node)
|
|
5652
|
+
this.visit(node.end_node);
|
|
5653
|
+
});
|
|
5503
5654
|
}
|
|
5504
5655
|
// --- Element Formatting Analysis Helpers ---
|
|
5505
5656
|
/**
|
|
@@ -5544,6 +5695,14 @@ class FormatPrinter extends Printer {
|
|
|
5544
5695
|
return false;
|
|
5545
5696
|
if (children.length === 0)
|
|
5546
5697
|
return true;
|
|
5698
|
+
const hasNonInlineChildElements = children.some(child => {
|
|
5699
|
+
if (isNode(child, HTMLElementNode)) {
|
|
5700
|
+
return !this.shouldRenderElementContentInline(child);
|
|
5701
|
+
}
|
|
5702
|
+
return false;
|
|
5703
|
+
});
|
|
5704
|
+
if (hasNonInlineChildElements)
|
|
5705
|
+
return false;
|
|
5547
5706
|
let hasLeadingHerbDisable = false;
|
|
5548
5707
|
for (const child of node.body) {
|
|
5549
5708
|
if (isNode(child, WhitespaceNode) || isPureWhitespaceNode(child)) {
|
|
@@ -5561,7 +5720,7 @@ class FormatPrinter extends Printer {
|
|
|
5561
5720
|
const fullInlineResult = this.tryRenderInlineFull(node, tagName, filterNodes(node.open_tag?.children, HTMLAttributeNode), node.body);
|
|
5562
5721
|
if (fullInlineResult) {
|
|
5563
5722
|
const totalLength = this.indent.length + fullInlineResult.length;
|
|
5564
|
-
return totalLength <= this.maxLineLength
|
|
5723
|
+
return totalLength <= this.maxLineLength;
|
|
5565
5724
|
}
|
|
5566
5725
|
return false;
|
|
5567
5726
|
}
|
|
@@ -5582,7 +5741,8 @@ class FormatPrinter extends Printer {
|
|
|
5582
5741
|
const openTagResult = this.renderInlineOpen(tagName, filterNodes(node.open_tag?.children, HTMLAttributeNode), false, [], node.open_tag?.children || []);
|
|
5583
5742
|
const childrenContent = this.renderChildrenInline(children);
|
|
5584
5743
|
const fullLine = openTagResult + childrenContent + `</${tagName}>`;
|
|
5585
|
-
|
|
5744
|
+
const totalLength = this.indent.length + fullLine.length;
|
|
5745
|
+
if (totalLength <= this.maxLineLength) {
|
|
5586
5746
|
return true;
|
|
5587
5747
|
}
|
|
5588
5748
|
}
|
|
@@ -5898,7 +6058,7 @@ class FormatPrinter extends Printer {
|
|
|
5898
6058
|
return false;
|
|
5899
6059
|
const firstWord = words[0];
|
|
5900
6060
|
const firstChar = firstWord[0];
|
|
5901
|
-
if (
|
|
6061
|
+
if (/\s/.test(firstChar)) {
|
|
5902
6062
|
return false;
|
|
5903
6063
|
}
|
|
5904
6064
|
lastUnit.unit.content += firstWord;
|
|
@@ -5912,6 +6072,12 @@ class FormatPrinter extends Printer {
|
|
|
5912
6072
|
node: textNode
|
|
5913
6073
|
});
|
|
5914
6074
|
}
|
|
6075
|
+
else if (endsWithWhitespace(textNode.content)) {
|
|
6076
|
+
result.push({
|
|
6077
|
+
unit: { content: ' ', type: 'text', isAtomic: false, breaksFlow: false },
|
|
6078
|
+
node: textNode
|
|
6079
|
+
});
|
|
6080
|
+
}
|
|
5915
6081
|
return true;
|
|
5916
6082
|
}
|
|
5917
6083
|
/**
|
|
@@ -5972,9 +6138,7 @@ class FormatPrinter extends Printer {
|
|
|
5972
6138
|
const hasWhitespace = this.hasWhitespaceBeforeNode(children, lastProcessedIndex, index, child);
|
|
5973
6139
|
const lastUnit = result[result.length - 1];
|
|
5974
6140
|
const lastIsAtomic = lastUnit.unit.isAtomic && (lastUnit.unit.type === 'erb' || lastUnit.unit.type === 'inline');
|
|
5975
|
-
|
|
5976
|
-
const startsWithClosingPunct = trimmed.length > 0 && /^[.!?:;]/.test(trimmed);
|
|
5977
|
-
if (lastIsAtomic && (!hasWhitespace || startsWithClosingPunct) && this.tryMergeTextAfterAtomic(result, child)) {
|
|
6141
|
+
if (lastIsAtomic && !hasWhitespace && this.tryMergeTextAfterAtomic(result, child)) {
|
|
5978
6142
|
return;
|
|
5979
6143
|
}
|
|
5980
6144
|
}
|
|
@@ -6450,6 +6614,41 @@ function resolveFormatOptions(options = {}) {
|
|
|
6450
6614
|
};
|
|
6451
6615
|
}
|
|
6452
6616
|
|
|
6617
|
+
const HERB_FORMATTER_PREFIX = "herb:formatter";
|
|
6618
|
+
const HERB_FORMATTER_IGNORE_PREFIX = `${HERB_FORMATTER_PREFIX} ignore`;
|
|
6619
|
+
/**
|
|
6620
|
+
* Check if an ERB content node is a herb:formatter ignore comment
|
|
6621
|
+
*/
|
|
6622
|
+
function isHerbFormatterIgnoreComment(node) {
|
|
6623
|
+
if (!isERBCommentNode(node))
|
|
6624
|
+
return false;
|
|
6625
|
+
const content = node?.content?.value || "";
|
|
6626
|
+
return content.trim() === HERB_FORMATTER_IGNORE_PREFIX;
|
|
6627
|
+
}
|
|
6628
|
+
/**
|
|
6629
|
+
* Check if the document contains a herb:formatter ignore directive anywhere.
|
|
6630
|
+
*/
|
|
6631
|
+
function hasFormatterIgnoreDirective(node) {
|
|
6632
|
+
const detector = new FormatterIgnoreDetector();
|
|
6633
|
+
detector.visit(node);
|
|
6634
|
+
return detector.hasIgnoreDirective;
|
|
6635
|
+
}
|
|
6636
|
+
/**
|
|
6637
|
+
* Visitor that detects if the AST contains a herb:formatter ignore directive.
|
|
6638
|
+
*/
|
|
6639
|
+
class FormatterIgnoreDetector extends Visitor {
|
|
6640
|
+
hasIgnoreDirective = false;
|
|
6641
|
+
visitERBContentNode(node) {
|
|
6642
|
+
if (isHerbFormatterIgnoreComment(node)) {
|
|
6643
|
+
this.hasIgnoreDirective = true;
|
|
6644
|
+
return;
|
|
6645
|
+
}
|
|
6646
|
+
if (this.hasIgnoreDirective)
|
|
6647
|
+
return;
|
|
6648
|
+
this.visitChildNodes(node);
|
|
6649
|
+
}
|
|
6650
|
+
}
|
|
6651
|
+
|
|
6453
6652
|
/**
|
|
6454
6653
|
* Formatter uses a Herb Backend to parse the source and then
|
|
6455
6654
|
* formats the resulting AST into a well-indented, wrapped string.
|
|
@@ -6494,6 +6693,8 @@ class Formatter {
|
|
|
6494
6693
|
return source;
|
|
6495
6694
|
if (isScaffoldTemplate(result))
|
|
6496
6695
|
return source;
|
|
6696
|
+
if (hasFormatterIgnoreDirective(result.value))
|
|
6697
|
+
return source;
|
|
6497
6698
|
const resolvedOptions = resolveFormatOptions({ ...this.options, ...options });
|
|
6498
6699
|
let node = result.value;
|
|
6499
6700
|
if (resolvedOptions.preRewriters.length > 0) {
|