11import { createRule } from '../factories/createRule' ;
22import { dropBaseIndent } from '../utilities/dropBaseIndent' ;
33import { isSqlQuery } from '../utilities/isSqlQuery' ;
4+ import { AST_NODE_TYPES } from '@typescript-eslint/utils' ;
45import { generate } from 'astring' ;
56import { format } from 'pg-formatter' ;
67
78type MessageIds = 'format' ;
89
910type Options = [
1011 {
12+ alignIndent ?: boolean ;
1113 ignoreBaseIndent ?: boolean ;
1214 ignoreExpressions ?: boolean ;
1315 ignoreInline ?: boolean ;
@@ -27,13 +29,23 @@ type Options = [
2729 } ,
2830] ;
2931
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+
3041export const rule = createRule < Options , MessageIds > ( {
3142 create : ( context ) => {
3243 // @ts -expect-error I am ont clear how to type this
3344 const placeholderRule = context . settings ?. sql ?. placeholderRule ;
3445
3546 const pluginOptions = context . options ?. [ 0 ] || { } ;
3647
48+ const alignIndent = pluginOptions . alignIndent === true ;
3749 const sqlTag = pluginOptions . sqlTag ?? 'sql' ;
3850 const ignoreExpressions = pluginOptions . ignoreExpressions === true ;
3951 const ignoreInline = pluginOptions . ignoreInline !== false ;
@@ -42,6 +54,8 @@ export const rule = createRule<Options, MessageIds>({
4254 pluginOptions . ignoreStartWithNewLine !== false ;
4355 const ignoreBaseIndent = pluginOptions . ignoreBaseIndent === true ;
4456
57+ const spaces = context . options ?. [ 1 ] ?. spaces ?? 4 ;
58+
4559 return {
4660 TemplateLiteral ( node ) {
4761 const tagName =
@@ -54,6 +68,14 @@ export const rule = createRule<Options, MessageIds>({
5468
5569 const sqlTagIsPresent = tagName === sqlTag ;
5670
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+
5779 if ( ignoreTagless && ! sqlTagIsPresent ) {
5880 return ;
5981 }
@@ -82,7 +104,10 @@ export const rule = createRule<Options, MessageIds>({
82104 literal = dropBaseIndent ( literal ) ;
83105 }
84106
85- let formatted = format ( literal , context . options [ 1 ] ) ;
107+ let formatted = format ( literal , {
108+ ...context . options [ 1 ] ,
109+ spaces,
110+ } ) ;
86111
87112 if (
88113 ignoreStartWithNewLine &&
@@ -96,6 +121,10 @@ export const rule = createRule<Options, MessageIds>({
96121 formatted = formatted . replace ( / \n \n $ / u, '\n' ) ;
97122 }
98123
124+ if ( alignIndent ) {
125+ formatted = padIndent ( formatted , indentAnchorOffset ) ;
126+ }
127+
99128 if ( formatted !== literal ) {
100129 context . report ( {
101130 fix : ( fixer ) => {
@@ -130,6 +159,7 @@ export const rule = createRule<Options, MessageIds>({
130159 } ,
131160 defaultOptions : [
132161 {
162+ alignIndent : true ,
133163 ignoreBaseIndent : false ,
134164 ignoreExpressions : false ,
135165 ignoreInline : true ,
@@ -162,6 +192,10 @@ export const rule = createRule<Options, MessageIds>({
162192 {
163193 additionalProperties : false ,
164194 properties : {
195+ alignIndent : {
196+ default : false ,
197+ type : 'boolean' ,
198+ } ,
165199 ignoreBaseIndent : {
166200 default : false ,
167201 type : 'boolean' ,
0 commit comments