-
Notifications
You must be signed in to change notification settings - Fork 60.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Content Linter Rule - Whitespace (#52622)
Co-authored-by: Rachael Sewell <[email protected]>
- Loading branch information
Showing
5 changed files
with
145 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
src/content-linter/lib/linting-rules/liquid-tag-whitespace.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { TokenKind } from 'liquidjs' | ||
|
||
import { getLiquidTokens, getPositionData } from '../helpers/liquid-utils.js' | ||
import { addFixErrorDetail } from '../helpers/utils.js' | ||
|
||
/* | ||
Liquid tags should start and end with one whitespace. For example: | ||
DO use a single whitespace character | ||
{% data <args> %} | ||
DON'T use 0 or more than 1 whitespace | ||
{%data <args> %} | ||
DON'T use more than 1 whitespace between args | ||
{%data arg1 arg2 %} | ||
*/ | ||
|
||
export const liquidTagWhitespace = { | ||
names: ['GHD042', 'liquid-tag-whitespace'], | ||
description: | ||
'Liquid tags should start and end with one whitespace. Liquid tag arguments should be separated by only one whitespace.', | ||
tags: ['liquid', 'format'], | ||
function: (params, onError) => { | ||
const content = params.lines.join('\n') | ||
const tokens = getLiquidTokens(content).filter((token) => token.kind === TokenKind.Tag) | ||
for (const token of tokens) { | ||
const { lineNumber, column, length } = getPositionData(token, params.lines) | ||
|
||
const range = [column, length] | ||
const tag = params.lines[lineNumber - 1].slice(column - 1, column - 1 + length) | ||
|
||
// Get just the opening and closing tags, which includes any whitespace | ||
// added before the tag name or any arguments | ||
const openTag = tag.slice(0, token.contentRange[0] - token.begin) | ||
const closeTag = tag.slice(-(token.end - token.contentRange[1])) | ||
|
||
const isOpenTagOneSpace = openTag !== openTag.trim() + ' ' | ||
const isCloseTagOneSpace = closeTag !== ' ' + closeTag.trim() | ||
|
||
const moreThanOneSpace = /\s{2,}/ | ||
const isArgOneSpace = moreThanOneSpace.test(tag) | ||
|
||
const fixedContent = | ||
openTag.trim() + ' ' + token.content.replace(moreThanOneSpace, ' ') + ' ' + closeTag.trim() | ||
|
||
if (isOpenTagOneSpace || isCloseTagOneSpace || isArgOneSpace) { | ||
addFixErrorDetail( | ||
onError, | ||
lineNumber, | ||
fixedContent, | ||
params.lines[lineNumber - 1].slice(column - 1, column - 1 + length), | ||
range, | ||
{ | ||
lineNumber, | ||
editColumn: column, | ||
deleteCount: length, | ||
insertText: fixedContent, | ||
}, | ||
) | ||
} | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { describe, expect, test } from 'vitest' | ||
|
||
import { runRule } from '../../lib/init-test.js' | ||
import { liquidTagWhitespace } from '../../lib/linting-rules/liquid-tag-whitespace.js' | ||
|
||
describe(liquidTagWhitespace.names.join(' - '), () => { | ||
test('liquid tags with correct whitespace pass', async () => { | ||
const markdown = [ | ||
'{% data variables.location.product_location %}', | ||
'{% assign my_variable = "value" %}', | ||
'{% if user %}Hello, {{ user.name }}{% endif %}', | ||
].join('\n') | ||
|
||
const result = await runRule(liquidTagWhitespace, { strings: { markdown } }) | ||
const errors = result.markdown | ||
expect(errors.length).toBe(0) | ||
}) | ||
|
||
test('liquid tags with incorrect whitespace fail', async () => { | ||
const markdown = [ | ||
'{%data variables.location.product_location %}', | ||
'{% assign my_variable = "value"%}', | ||
'{% if user %}Hello, {{ user.name }} {%endif %}', | ||
'{% data variables.location.product_location %}', | ||
'{%-data variables.location.product_location -%}', | ||
'{%- assign my_variable = "value"-%}', | ||
'{%- if user -%}Hello, {{ user.name }} {%endif %}', | ||
'{%- data variables.location.product_location -%}', | ||
].join('\n') | ||
|
||
const result = await runRule(liquidTagWhitespace, { strings: { markdown } }) | ||
const errors = result.markdown | ||
expect(errors.length).toBe(8) | ||
expect(errors[2].lineNumber).toBe(3) | ||
expect(errors[2].fixInfo).toEqual({ | ||
deleteCount: 10, | ||
editColumn: 37, | ||
lineNumber: 3, | ||
insertText: '{% endif %}', | ||
}) | ||
}) | ||
|
||
test('liquid tags with multiple spaces between arguments fail', async () => { | ||
const markdown = [ | ||
'{% assign my_variable = "value" %}', | ||
'{% if user %}Hello, {{ user.name }}{% endif %}', | ||
].join('\n') | ||
|
||
const result = await runRule(liquidTagWhitespace, { strings: { markdown } }) | ||
const errors = result.markdown | ||
expect(errors.length).toBe(2) | ||
expect(errors[1].lineNumber).toBe(2) | ||
expect(errors[0].fixInfo).toEqual({ | ||
deleteCount: 35, | ||
editColumn: 1, | ||
lineNumber: 1, | ||
insertText: '{% assign my_variable = "value" %}', | ||
}) | ||
}) | ||
|
||
test('liquid tags with single spaces between arguments pass', async () => { | ||
const markdown = [ | ||
'{% assign my_variable = "value" %}', | ||
'{% if user %}Hello, {{ user.name }}{% endif %}', | ||
].join('\n') | ||
|
||
const result = await runRule(liquidTagWhitespace, { strings: { markdown } }) | ||
const errors = result.markdown | ||
expect(errors.length).toBe(0) | ||
}) | ||
}) |