1
1
import { createRule } from '../factories/createRule' ;
2
2
import { dropBaseIndent } from '../utilities/dropBaseIndent' ;
3
3
import { isSqlQuery } from '../utilities/isSqlQuery' ;
4
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils' ;
4
5
import { generate } from 'astring' ;
5
6
import { format } from 'pg-formatter' ;
6
7
7
8
type MessageIds = 'format' ;
8
9
9
10
type Options = [
10
11
{
12
+ alignIndent ?: boolean ;
11
13
ignoreBaseIndent ?: boolean ;
12
14
ignoreExpressions ?: boolean ;
13
15
ignoreInline ?: boolean ;
@@ -27,13 +29,23 @@ type Options = [
27
29
} ,
28
30
] ;
29
31
32
+ const padIndent = ( subject : string , spaces : number ) => {
33
+ return subject
34
+ . split ( '\n' )
35
+ . map ( ( line ) => {
36
+ return line . length > 0 ? ' ' . repeat ( spaces ) + line : line ;
37
+ } )
38
+ . join ( '\n' ) ;
39
+ } ;
40
+
30
41
export const rule = createRule < Options , MessageIds > ( {
31
42
create : ( context ) => {
32
43
// @ts -expect-error I am ont clear how to type this
33
44
const placeholderRule = context . settings ?. sql ?. placeholderRule ;
34
45
35
46
const pluginOptions = context . options ?. [ 0 ] || { } ;
36
47
48
+ const alignIndent = pluginOptions . alignIndent === true ;
37
49
const sqlTag = pluginOptions . sqlTag ?? 'sql' ;
38
50
const ignoreExpressions = pluginOptions . ignoreExpressions === true ;
39
51
const ignoreInline = pluginOptions . ignoreInline !== false ;
@@ -42,6 +54,8 @@ export const rule = createRule<Options, MessageIds>({
42
54
pluginOptions . ignoreStartWithNewLine !== false ;
43
55
const ignoreBaseIndent = pluginOptions . ignoreBaseIndent === true ;
44
56
57
+ const spaces = context . options ?. [ 1 ] ?. spaces ?? 4 ;
58
+
45
59
return {
46
60
TemplateLiteral ( node ) {
47
61
const tagName =
@@ -54,6 +68,14 @@ export const rule = createRule<Options, MessageIds>({
54
68
55
69
const sqlTagIsPresent = tagName === sqlTag ;
56
70
71
+ let indentAnchorOffset = node . loc . start . column ;
72
+
73
+ if ( node . parent . type === AST_NODE_TYPES . TaggedTemplateExpression ) {
74
+ indentAnchorOffset = node . parent . loc . start . column ;
75
+ }
76
+
77
+ indentAnchorOffset += spaces ;
78
+
57
79
if ( ignoreTagless && ! sqlTagIsPresent ) {
58
80
return ;
59
81
}
@@ -82,7 +104,10 @@ export const rule = createRule<Options, MessageIds>({
82
104
literal = dropBaseIndent ( literal ) ;
83
105
}
84
106
85
- let formatted = format ( literal , context . options [ 1 ] ) ;
107
+ let formatted = format ( literal , {
108
+ ...context . options [ 1 ] ,
109
+ spaces,
110
+ } ) ;
86
111
87
112
if (
88
113
ignoreStartWithNewLine &&
@@ -96,6 +121,10 @@ export const rule = createRule<Options, MessageIds>({
96
121
formatted = formatted . replace ( / \n \n $ / u, '\n' ) ;
97
122
}
98
123
124
+ if ( alignIndent ) {
125
+ formatted = padIndent ( formatted , indentAnchorOffset ) ;
126
+ }
127
+
99
128
if ( formatted !== literal ) {
100
129
context . report ( {
101
130
fix : ( fixer ) => {
@@ -130,6 +159,7 @@ export const rule = createRule<Options, MessageIds>({
130
159
} ,
131
160
defaultOptions : [
132
161
{
162
+ alignIndent : true ,
133
163
ignoreBaseIndent : false ,
134
164
ignoreExpressions : false ,
135
165
ignoreInline : true ,
@@ -162,6 +192,10 @@ export const rule = createRule<Options, MessageIds>({
162
192
{
163
193
additionalProperties : false ,
164
194
properties : {
195
+ alignIndent : {
196
+ default : false ,
197
+ type : 'boolean' ,
198
+ } ,
165
199
ignoreBaseIndent : {
166
200
default : false ,
167
201
type : 'boolean' ,
0 commit comments