Skip to content

Commit

Permalink
(feat) Support range ignores in HTML top level (#226)
Browse files Browse the repository at this point in the history
`<!-- prettier-ignore-start --> ... <!-- prettier-ignore-end -->` is now supported at HTML top level
Closes #225
  • Loading branch information
dummdidumm committed May 10, 2021
1 parent 9d1486e commit bb132d9
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 16 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# prettier-plugin-svelte changelog

## 2.2.1 (Unreleased)
## 2.3.0 (Unreleased)

* (fix) adjust snip regex to not break commented-out script/style tags ([#212](https://github.com/sveltejs/prettier-plugin-svelte/issues/212))
* (fix) Don't snip style tag that is inside script tag ([#219](https://github.com/sveltejs/prettier-plugin-svelte/issues/219), [#70](https://github.com/sveltejs/prettier-plugin-svelte/issues/70))
* (fix) Better formatting of long attribute values with mustache tags inbetween ([#221](https://github.com/sveltejs/prettier-plugin-svelte/pull/221))
* (fix) Format properly when using Prettier 2.3.0+ ([#222](https://github.com/sveltejs/prettier-plugin-svelte/pull/222))
* (fix) Keep parantheses in script tags for which JS is assumed ([#218](https://github.com/sveltejs/prettier-plugin-svelte/issues/218))
* (feat) Support range ignores in HTML top level ([#225](https://github.com/sveltejs/prettier-plugin-svelte/issues/225))

## 2.2.0

Expand Down
34 changes: 23 additions & 11 deletions src/print/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ import {
trimTextNodeRight,
canOmitSoftlineBeforeClosingTag,
getNextNode,
isIgnoreStartDirective,
isIgnoreEndDirective,
isNodeTopLevelHTML,
} from './node-helpers';
import {
ASTNode,
Expand Down Expand Up @@ -71,6 +74,7 @@ declare module 'prettier' {
}

let ignoreNext = false;
let ignoreRange = false;
let svelteOptionsDoc: Doc | undefined;

function groupConcat(contents: doc.builders.Doc[]): doc.builders.Doc {
Expand All @@ -95,8 +99,13 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
];
const node = n as Node;

if (ignoreNext && (node.type !== 'Text' || !isEmptyTextNode(node))) {
ignoreNext = false;
if (
(ignoreNext || (ignoreRange && !isIgnoreEndDirective(node))) &&
(node.type !== 'Text' || !isEmptyTextNode(node))
) {
if (ignoreNext) {
ignoreNext = false;
}
return concat(
flatten(
options.originalText
Expand Down Expand Up @@ -578,14 +587,16 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
case 'Comment': {
const nodeAfterComment = getNextNode(path);

/**
* If there is no sibling node that starts right after us but the parent indicates
* that there used to be, that means that node was actually an embedded `<style>`
* or `<script>` node that was cut out.
* If so, the comment does not refer to the next line we will see.
* The `embed` function handles printing the comment in the right place.
*/
if (
if (isIgnoreStartDirective(node) && isNodeTopLevelHTML(node, path)) {
ignoreRange = true;
} else if (isIgnoreEndDirective(node) && isNodeTopLevelHTML(node, path)) {
ignoreRange = false;
} else if (
// If there is no sibling node that starts right after us but the parent indicates
// that there used to be, that means that node was actually an embedded `<style>`
// or `<script>` node that was cut out.
// If so, the comment does not refer to the next line we will see.
// The `embed` function handles printing the comment in the right place.
doesEmbedStartAfterNode(node, path) ||
(isEmptyTextNode(nodeAfterComment) &&
doesEmbedStartAfterNode(nodeAfterComment, path))
Expand Down Expand Up @@ -678,6 +689,7 @@ function printTopLevelParts(

// Need to reset these because they are global and could affect the next formatting run
ignoreNext = false;
ignoreRange = false;
svelteOptionsDoc = undefined;

// If this is invoked as an embed of markdown, remove the last hardline.
Expand Down Expand Up @@ -967,7 +979,7 @@ function prepareChildren(children: Node[], path: FastPath, print: PrintFn): Node
}

function isCommentFollowedByOptions(node: Node, idx: number): node is CommentNode {
if (node.type !== 'Comment') {
if (node.type !== 'Comment' || isIgnoreEndDirective(node) || isIgnoreStartDirective(node)) {
return false;
}

Expand Down
26 changes: 22 additions & 4 deletions src/print/node-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ export function getLeadingComment(path: FastPath): CommentNode | undefined {
let node: Node = path.getNode();
let prev: Node | undefined = siblings.find((child) => child.end === node.start);
while (prev) {
if (prev.type === 'Comment') {
if (
prev.type === 'Comment' &&
!isIgnoreStartDirective(prev) &&
!isIgnoreEndDirective(prev)
) {
return prev;
} else if (isEmptyTextNode(prev)) {
node = prev;
Expand All @@ -127,20 +131,26 @@ export function getLeadingComment(path: FastPath): CommentNode | undefined {
* at the specified position?
*/
export function doesEmbedStartAfterNode(node: Node, path: FastPath, siblings = getSiblings(path)) {
const position = node.end;
const root = path.stack[0];
// If node is not at the top level of html, an embed cannot start after it,
// because embeds are only at the top level
if (!root.html || !root.html.children || !root.html.children.includes(node)) {
if (!isNodeTopLevelHTML(node, path)) {
return false;
}

const position = node.end;
const root = path.stack[0];

const embeds = [root.css, root.html, root.instance, root.js, root.module] as Node[];

const nextNode = siblings[siblings.indexOf(node) + 1];
return embeds.find((n) => n && n.start >= position && (!nextNode || n.end <= nextNode.start));
}

export function isNodeTopLevelHTML(node: Node, path: FastPath): boolean {
const root = path.stack[0];
return !!root.html && !!root.html.children && root.html.children.includes(node);
}

export function isEmptyTextNode(node: Node | undefined): node is TextNode {
return !!node && node.type === 'Text' && getUnencodedText(node).trim() === '';
}
Expand All @@ -149,6 +159,14 @@ export function isIgnoreDirective(node: Node | undefined | null): boolean {
return !!node && node.type === 'Comment' && node.data.trim() === 'prettier-ignore';
}

export function isIgnoreStartDirective(node: Node | undefined | null): boolean {
return !!node && node.type === 'Comment' && node.data.trim() === 'prettier-ignore-start';
}

export function isIgnoreEndDirective(node: Node | undefined | null): boolean {
return !!node && node.type === 'Comment' && node.data.trim() === 'prettier-ignore-end';
}

export function printRaw(
node:
| ElementNode
Expand Down
23 changes: 23 additions & 0 deletions test/formatting/samples/prettier-ignore-range-1/input.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script>
const a = true;
</script>

<div>

I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->

<div>I need to adhere sadly


</div>
18 changes: 18 additions & 0 deletions test/formatting/samples/prettier-ignore-range-1/output.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
const a = true;
</script>

<div>I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->

<div>I need to adhere sadly</div>
17 changes: 17 additions & 0 deletions test/formatting/samples/prettier-ignore-range-2/input.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div>

I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->
<script>
const a = true;
</script>
16 changes: 16 additions & 0 deletions test/formatting/samples/prettier-ignore-range-2/output.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script>
const a = true;
</script>

<div>I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->
14 changes: 14 additions & 0 deletions test/formatting/samples/prettier-ignore-range-wrong/input.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div>
<!-- prettier-ignore-start -->

<div > no format madness here </div>

<p>
no
toplevel
</p>

<!-- prettier-ignore-end -->
</div>

<div>We all need to adhere sadly</div>
11 changes: 11 additions & 0 deletions test/formatting/samples/prettier-ignore-range-wrong/output.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div>
<!-- prettier-ignore-start -->

<div>no format madness here</div>

<p>no toplevel</p>

<!-- prettier-ignore-end -->
</div>

<div>We all need to adhere sadly</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<div>

I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->

<div>I need to adhere sadly


</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->

<!-- prettier-ignore -->
<p>
I'm
freeeee!
</p>
<div>I need to adhere sadly


</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div>I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->

<div>I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->

<!-- prettier-ignore -->
<p>
I'm
freeeee!
</p>
<div>I need to adhere sadly</div>
18 changes: 18 additions & 0 deletions test/printer/samples/prettier-ignore-range.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
const a = true;
</script>

<div>I need to adhere sadly</div>

<!-- prettier-ignore-start -->

<div > format madness here </div>

<p>
I'm
freeeee!
</p>

<!-- prettier-ignore-end -->

<div>I need to adhere sadly</div>

0 comments on commit bb132d9

Please sign in to comment.