Skip to main content

Blank lines

How the author's blank lines — the one grouping signal a template has — survive formatting.

Each pair below is a real, passing case from dfmt's test corpus (suites/dfmt-jinja/cases/blank-lines/): the template as written, then the same template after dfmt — every Jinja tag reproduced exactly, the SQL laid out around it. 31 examples.

A blank above a guard between ctes stays out of its else​

Before

with emails as (select * from a),

{% if var('x', False) %}
o as (select * from b),
{% else %}
{% set w = 1 %}
{% if w is string %} {% set w = [w] %} {% endif %}

{% set v = 2 %}
{% if v is string %} {% set v = [v] %} {% endif %}

o as (select * from c),
{% endif %}
d as (select * from o)
select * from d

After

with
emails as (select * from a),

{% if var('x', False) %}
o as (select * from b),
{% else %}
{% set w = 1 %}
{% if w is string %}
{% set w = [w] %}
{% endif %}

{% set v = 2 %}
{% if v is string %}
{% set v = [v] %}
{% endif %}

o as (select * from c),
{% endif %}

d as (select * from o)
select *
from d

A blank above a right trimmed set stays above it​

Before

select
a,
b

{% set states = ['x','y'] -%}
{% for s in states -%}
, max( x ) as {{ s }}_q
{% endfor -%}
from t

After

select
a,
b

{% set states = ['x','y'] -%}
{% for s in states -%}
, max(x) as {{ s }}_q
{% endfor -%}
from t

A blank after a trailing comment construct stays​

Before

with
joined as (

select customer.*, address.address_id as default_address_id {# QUESTION: add other helpful fields? #}

from customer
left join address on address.customer_id = customer.customer_id
)
select *
from joined

After

with
joined as (

select customer.*, address.address_id as default_address_id {# QUESTION: add other helpful fields? #}

from customer
left join address on address.customer_id = customer.customer_id
)
select *
from joined

A blank below an own line set stays​

Left unchanged — already in dfmt's shape:

with
windows as (

{% set metric = 'sum(total_price_in_month)' %}

select
*,
{{ metric }} over (partition by customer_id order by date_month) as total_price_lifetime,
count(order_count_in_month) over (partition by customer_id order by date_month) as order_count_lifetime
from base
)
select total_price_lifetime
from windows

A blank line after a macro definition stays​

Before

{% macro base_accounts() -%}
select a, b
from t
{%- endmacro %}

{{ base_accounts() }}

After

{% macro base_accounts() -%}
select a, b
from t
{%- endmacro %}

{{ base_accounts() }}

A blank run after a head construct collapses to one​

dialect ansi

Before

{{ config(materialized='table') }}



select a from t

After

{{ config(materialized = 'table') }}

select a
from t

A comment only branch does not steal the blank above its guard​

Before

select distinct token_address, decimals, 1 as weight
from {{ ref('prices_hourly') }}
where

{% if is_incremental() %}
hour >= timestamp_sub(current_timestamp(), interval 31 day) and
{% else %}
-- hour >= twelve months back
{% endif %}

decimals is not null

After

select distinct token_address, decimals, 1 as weight
from {{ ref('prices_hourly') }}
where

{% if is_incremental() %}
hour >= timestamp_sub(current_timestamp(), interval 31 day) and
{% else %}
-- hour >= twelve months back
{% endif %}

decimals is not null

A file of only constructs is still laid out​

dialect ansi

Before

{{ config(materialized='table') }}


{% set x = 1 %}

After

{{ config(materialized = 'table') }}

{% set x = 1 %}

A glue seam between two blocks keeps the authors blanks​

Before

{% set contexts = [] %}

{% if not var('disable_page', false) -%}
{% do contexts.append('page') %}
{% endif -%}

{% if not var('disable_cart', false) -%}
{% do contexts.append('cart') %}
{% endif -%}


{% if var('enable_mobile', true) %}
{% do contexts.append('mobile') %}
{% endif -%}

select ticket_id
from enriched

After

{% set contexts = [] %}

{% if not var('disable_page', false) -%}
{% do contexts.append('page') %}
{% endif -%}

{% if not var('disable_cart', false) -%}
{% do contexts.append('cart') %}
{% endif -%}

{% if var('enable_mobile', true) %}
{% do contexts.append('mobile') %}
{% endif -%}

select ticket_id
from enriched

A head construct is a statement and gets a blank line​

dialect ansi

Before

{{ config(materialized='table') }}
select a from t

After

{{ config(materialized = 'table') }}

select a
from t

A left trimmed follower falsifies the claim before it​

Before

{% set contexts = [] %}

{%- if var("enable_youtube") -%}
{% do contexts.append('youtube') %}
{%- endif %}

{% set base_events_query = 'select id from events' %}

with base_query as (
select id
from t
)
select *
from base_query

After

{% set contexts = [] %}
{%- if var("enable_youtube") -%}
{% do contexts.append('youtube') %}
{%- endif %}

{% set base_events_query = 'select id from events' %}

with base_query as (select id from t)
select *
from base_query

A left trimmed follower falsifies the close anchor before it​

Before

{% set contexts = [] %}

{% if var("enable_ad_break", true) %}
{% do contexts.append('ad_break') %}
{% endif %}
{%- if var("enable_youtube") -%}
{% do contexts.append('youtube') %}
{%- endif %}
{% if var("enable_web", true) %}
{% do contexts.append('web') %}
{% endif %}

{% set base_events_query = 'select id from events' %}

with base_query as (
select id
from t
)
select *
from base_query

After

{% set contexts = [] %}

{% if var("enable_ad_break", true) %}
{% do contexts.append('ad_break') %}
{% endif %}
{%- if var("enable_youtube") -%}
{% do contexts.append('youtube') %}
{%- endif %}
{% if var("enable_web", true) %}
{% do contexts.append('web') %}
{% endif %}

{% set base_events_query = 'select id from events' %}

with base_query as (select id from t)
select *
from base_query

A macros own blanks are not the authors​

Before

{% set v %}

nullif(trim(x), '')

{% endset %}
select
{{ v }} as a,
{{ v }} as b,
y as c
from t

After

{% set v %}
nullif(trim(x), '')
{% endset %}

select {{ v }} as a, {{ v }} as b, y as c
from t

A macros own blanks before an eof comment are not the authors​

Before

{% macro tvl(chain) -%}
select date, '{{ chain }}' as chain, tvl
from tvl_daily_sum
where date is not null

{% endmacro %}
{{ tvl("ethereum") }}
-- ("0xfffa78c979c2f787b16eac7c7e9c77b11feb77fb"),

After

{% macro tvl(chain) -%}
select date, '{{ chain }}' as chain, tvl
from tvl_daily_sum
where date is not null

{% endmacro %}

{{ tvl("ethereum") }}
-- ("0xfffa78c979c2f787b16eac7c7e9c77b11feb77fb"),

A minted blank does not double through a block open​

Before

{{config(enabled = true)}}
{% if true %}
{{config(alias='customer_events_xa',
materialized="view")}}
select 1 as a
{% endif %}

After

{{ config(enabled = true) }}

{% if true %}
{{ config(alias = 'customer_events_xa', materialized = "view") }}
select 1 as a
{% endif %}

A set run inside a taken guard keeps its blanks​

Before

{% if var('x', true) == true -%}

{%- set a -%}
1
{%- endset -%}

select {{ a }} as v
from t

{% endif %}

After

{% if var('x', true) == true -%}

{%- set a -%}
1
{%- endset -%}

select {{ a }} as v
from t

{% endif %}

A taken branchs trailing blank stays above the next tag​

Before

with
base as (
select x
from t
),

{% if flag %}
a as (
select x
from base
),

{% else %}
b as (
select x
from base
),
{% endif %}
final as (
select x
from base
)
select x
from final

After

with
base as (select x from t),

{% if flag %}
a as (select x from base),

{% else %}
b as (select x from base),
{% endif %}

final as (select x from base)
select x
from final

A trailing construct keeps one blank​

dialect ansi

Before

select a from t


{% set x = 1 %}

After

select a
from t

{% set x = 1 %}

A trimmed setblocks claims do not ratchet​

Before

{%- set extension_columns -%}
, immune.data_source
{%- endset -%}

{% if var('enable_normalize_engine', false) != true %}


select
immune.immunization_id
{{ extension_columns }}
from immunization
{% endif %}

After

{%- set extension_columns -%}
, immune.data_source
{%- endset -%}

{% if var('enable_normalize_engine', false) != true %}
select immune.immunization_id {{ extension_columns }}
from immunization
{% endif %}

An expansions whitespace does not shift the authors terminator​

Before

{{ blanks }}
-- depends_on: a
-- depends_on: b

After

{{ blanks }}

-- depends_on: a
-- depends_on: b

An expansions whitespace settles after a right trimmed set​

Left unchanged — already in dfmt's shape:

-- n
{%- set r = [] -%}
{{ blanks }}
-- t

An interpolations trailing newline is not an author blank​

Before

{%- if convs %}
select
session_identifier
{% if enable_conversions %}
from a
{% else %}
from b
where 1 = 1
{% if ua_bot_filter %}
{{ bots }}
{% endif %}
{% endif %}
group by session_identifier
{%- endif %}

After

{%- if convs %}
select session_identifier
{% if enable_conversions %}
from a
{% else %}
from b
where
1 = 1
{% if ua_bot_filter %}
{{ bots }}
{% endif %}
{% endif %}
group by session_identifier
{%- endif %}

An untaken glue guard after a construct holds its blank​

Before

{{ config(materialized='incremental') }}

{% if var('never', false) -%}
{% set results = ['a', 'b'] %}
{% endif -%}

with field_history as (

select
ticket_id,
valid_starting_at,
case when value is null then 'is_null' else value end as value

from enriched

)

select * from field_history

After

{{ config(materialized = 'incremental') }}

{% if var('never', false) -%}
{% set results = ['a', 'b'] %}
{% endif -%}

with
field_history as (

select ticket_id, valid_starting_at, case when value is null then 'is_null' else value end as value

from enriched

)

select *
from field_history

Between independent blocks​

Before

select
a,

{% if web %}
web_col,
{% endif %}

{% if mobile %}
mobile_col,
{% endif %}

z
from t

After

select
a,

{% if web %}
web_col,
{% endif %}

{% if mobile %}
mobile_col,
{% endif %}

z
from t

Blank above a comment stays above it​

Left unchanged — already in dfmt's shape:

select
a,
spend

{# a note about the fields #}
{%- set check = [] %}
from t

Blanks above the first construct are dropped​

dialect ansi

Before




{{ config(materialized='table') }}
select a from t

After

{{ config(materialized = 'table') }}

select a
from t

Never indented into spaces​

Before

select
{% if flag %}
a,

b,
{% endif %}
c
from t

After

select
{% if flag %}
a,

b,
{% endif %}
c
from t

No blank invented between an untaken tail and its comments​

Left unchanged — already in dfmt's shape:

select *
from {{ ref("spined") }}
{#
on the live data view.
#}
-- noqa: disable=LT02
{% if flag -%}
where materialized_at > now()
{%- endif %}
-- noqa: enable=all

Stacked untaken endifs mint no blank​

Before

with
src as (
select x
from t
{% if var('deep', false) %}
where x > 0
{% if is_incremental() %}
and x > (select max(x) from {{ this }})
{% endif %}
{% endif %}
),
final as (
select x
from src
)
select x
from final

After

with
src as (
select x
from t
{% if var('deep', false) %}
where
x > 0
{% if is_incremental() %}
and x > (select max(x) from {{ this }})
{% endif %}
{% endif %}
),

final as (select x from src)
select x
from final

Two adjacent head constructs are separated​

dialect ansi

Before

{{ config(materialized='table') }}
{% set unit = 'day' %}

select a from t

After

{{ config(materialized = 'table') }}

{% set unit = 'day' %}

select a
from t

Two passes agree about an authors blank below an expansion​

Before

{{- head -}}

-- n
{%- set r = [] -%}
{{ blanks }}

-- t

After

{{- head -}}
-- n
{%- set r = [] -%}
{{ blanks }}

-- t