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