-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add new rule django_block_translate_trimmed
- the rule will enforce the usage of `trimmed` when blocktranslate or blocktrans is in use
- Loading branch information
LB Johnston
committed
Apr 13, 2022
1 parent
4c36043
commit dce3e2d
Showing
10 changed files
with
279 additions
and
3 deletions.
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
Empty file.
69 changes: 69 additions & 0 deletions
69
curlylint/rules/django_block_translate_trimmed/django_block_translate_trimmed.py
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,69 @@ | ||
from curlylint import ast | ||
from curlylint.check_node import CheckNode, build_tree | ||
from curlylint.issue import Issue | ||
|
||
DJANGO_FORMS_RENDERING = "django_block_translate_trimmed" | ||
|
||
RULE = { | ||
"id": "django_block_translate_trimmed", | ||
"type": "internationalisation", | ||
"docs": { | ||
"description": "Enforces the use of Django’s `trimmed` option when using `blocktranslate`/`blocktrans` so that translations do not contain leading or trailing whitespace.", | ||
"url": "https://www.curlylint.org/docs/rules/django_block_translate_trimmed", | ||
"impact": "Serious", | ||
"tags": ["cat:language"], | ||
"resources": [ | ||
"[Django translations](https://docs.djangoproject.com/en/stable/topics/i18n/translation/)", | ||
], | ||
}, | ||
"schema": { | ||
"$schema": "http://json-schema.org/draft/2019-09/schema#", | ||
"oneOf": [ | ||
{ | ||
"const": True, | ||
"title": "Template tags of blocktranslate or blocktrans must use the trimmed option", | ||
"examples": [True], | ||
} | ||
], | ||
}, | ||
} | ||
|
||
BLOCK_NAMES = ["blocktranslate", "blocktrans"] | ||
|
||
|
||
def find_valid(node, file): | ||
|
||
if isinstance(node.value, ast.JinjaElement): | ||
for part in node.value.parts: | ||
|
||
tag = part.tag | ||
|
||
if tag.name in BLOCK_NAMES: | ||
if "trimmed" not in tag.content.split(" "): | ||
return [ | ||
Issue.from_node( | ||
file, | ||
node, | ||
f"`{tag}` must use the `trimmed` option", | ||
DJANGO_FORMS_RENDERING, | ||
) | ||
] | ||
|
||
if not node.children: | ||
return [] | ||
|
||
return sum( | ||
(find_valid(child, file) for child in node.children), | ||
[], | ||
) | ||
|
||
|
||
def django_block_translate_trimmed(file, target): | ||
root = CheckNode(None) | ||
build_tree(root, file.tree) | ||
src = file.source.lower() | ||
|
||
if "blocktrans" in src or "blocktranslate" in src: | ||
return find_valid(root, file) | ||
|
||
return [] |
90 changes: 90 additions & 0 deletions
90
curlylint/rules/django_block_translate_trimmed/django_block_translate_trimmed_test.json
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,90 @@ | ||
[ | ||
{ | ||
"label": "Using blocktranslate with trimmed", | ||
"template": "{% blocktranslate trimmed %} some value {% endblocktranslate %}", | ||
"example": true, | ||
"config": true, | ||
"output": [] | ||
}, | ||
{ | ||
"label": "Using blocktranslate without trimmed", | ||
"template": "{% blocktranslate %} some value {% endblocktranslate %}", | ||
"example": true, | ||
"config": true, | ||
"output": [ | ||
{ | ||
"file": "test.html", | ||
"column": 1, | ||
"line": 1, | ||
"code": "django_block_translate_trimmed", | ||
"message": "`{% blocktranslate %}` must use the `trimmed` option" | ||
} | ||
] | ||
}, | ||
{ | ||
"label": "Using blocktrans with trimmed", | ||
"template": "{% blocktrans trimmed %} some value {% endblocktrans %}", | ||
"example": true, | ||
"config": true, | ||
"output": [] | ||
}, | ||
{ | ||
"label": "Using blocktrans without trimmed", | ||
"template": "{% blocktrans %} some value {% endblocktrans %}", | ||
"example": true, | ||
"config": true, | ||
"output": [ | ||
{ | ||
"file": "test.html", | ||
"column": 1, | ||
"line": 1, | ||
"code": "django_block_translate_trimmed", | ||
"message": "`{% blocktrans %}` must use the `trimmed` option" | ||
} | ||
] | ||
}, | ||
{ | ||
"label": "Using blocktranslate with trimmed and other options", | ||
"template": "{% blocktranslate trimmed with time_period=revision.created_at|timesince_simple %} some value {% endblocktranslate %}", | ||
"example": true, | ||
"config": true, | ||
"output": [] | ||
}, | ||
{ | ||
"label": "Using blocktranslate without trimmed but with other options", | ||
"template": "{% blocktranslate count counter=list|length %} some value {% endblocktranslate %}", | ||
"example": true, | ||
"config": true, | ||
"output": [ | ||
{ | ||
"file": "test.html", | ||
"column": 1, | ||
"line": 1, | ||
"code": "django_block_translate_trimmed", | ||
"message": "`{% blocktranslate count counter=list|length %}` must use the `trimmed` option" | ||
} | ||
] | ||
}, | ||
{ | ||
"label": "Using blocktrans with other options", | ||
"template": "{% blocktrans trimmed with book_t=book|title %} some value {% endblocktrans %}", | ||
"example": true, | ||
"config": true, | ||
"output": [] | ||
}, | ||
{ | ||
"label": "Using blocktrans without trimmed but with other options", | ||
"template": "{% blocktrans with book_t=book|title %} some value {% endblocktrans %}", | ||
"example": true, | ||
"config": true, | ||
"output": [ | ||
{ | ||
"file": "test.html", | ||
"column": 1, | ||
"line": 1, | ||
"code": "django_block_translate_trimmed", | ||
"message": "`{% blocktrans with book_t=book|title %}` must use the `trimmed` option" | ||
} | ||
] | ||
} | ||
] |
10 changes: 10 additions & 0 deletions
10
curlylint/rules/django_block_translate_trimmed/django_block_translate_trimmed_test.py
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,10 @@ | ||
import unittest | ||
|
||
from curlylint.rules.rule_test_case import RulesTestMeta | ||
|
||
from .django_block_translate_trimmed import django_block_translate_trimmed | ||
|
||
|
||
class TestRule(unittest.TestCase, metaclass=RulesTestMeta): | ||
fixtures = __file__.replace(".py", ".json") | ||
rule = django_block_translate_trimmed |
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
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,96 @@ | ||
--- | ||
# This file is auto-generated, please do not update manually. | ||
id: django_block_translate_trimmed | ||
title: django_block_translate_trimmed | ||
custom_edit_url: https://github.com/thibaudcolas/curlylint/edit/main/curlylint/rules/django_block_translate_trimmed/django_block_translate_trimmed.py | ||
--- | ||
|
||
import Tabs from "@theme/Tabs"; | ||
import TabItem from "@theme/TabItem"; | ||
import CodeSnippet from "@theme/CodeSnippet"; | ||
|
||
> Enforces the use of Django’s `trimmed` option when using `blocktranslate`/`blocktrans` so that translations do not contain leading or trailing whitespace. | ||
> | ||
> User impact: **Serious** | ||
This rule supports the following configuration: | ||
|
||
<Tabs | ||
groupId="config-language" | ||
defaultValue="toml" | ||
values={[ | ||
{ label: "TOML", value: "toml" }, | ||
{ label: "Shell", value: "shell" }, | ||
]} | ||
> | ||
<TabItem value="toml"> | ||
<CodeSnippet | ||
snippet={`# Template tags of blocktranslate or blocktrans must use the trimmed option\ndjango_block_translate_trimmed = true`} | ||
annotations={[]} | ||
lang="toml" | ||
/> | ||
</TabItem> | ||
<TabItem value="shell"> | ||
<CodeSnippet | ||
snippet={`# Template tags of blocktranslate or blocktrans must use the trimmed option\ncurlylint --rule 'django_block_translate_trimmed: true' .`} | ||
annotations={[]} | ||
lang="shell" | ||
/> | ||
</TabItem> | ||
</Tabs> | ||
|
||
## Success | ||
|
||
<Tabs | ||
groupId="config-language" | ||
defaultValue="toml" | ||
values={[ | ||
{ label: "TOML", value: "toml" }, | ||
{ label: "Shell", value: "shell" }, | ||
]} | ||
> | ||
<TabItem value="toml"> | ||
<CodeSnippet | ||
snippet={`<!-- Good: Using blocktranslate with trimmed -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktranslate trimmed %} some value {% endblocktranslate %}\n<!-- Good: Using blocktrans with trimmed -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktrans trimmed %} some value {% endblocktrans %}\n<!-- Good: Using blocktranslate with trimmed and other options -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktranslate trimmed with time_period=revision.created_at|timesince_simple %} some value {% endblocktranslate %}\n<!-- Good: Using blocktrans with other options -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktrans trimmed with book_t=book|title %} some value {% endblocktrans %}`} | ||
annotations={[]} | ||
lang="html" | ||
/> | ||
</TabItem> | ||
<TabItem value="shell"> | ||
<CodeSnippet | ||
snippet={`<!-- Good: Using blocktranslate with trimmed -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktranslate trimmed %} some value {% endblocktranslate %}\n<!-- Good: Using blocktrans with trimmed -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktrans trimmed %} some value {% endblocktrans %}\n<!-- Good: Using blocktranslate with trimmed and other options -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktranslate trimmed with time_period=revision.created_at|timesince_simple %} some value {% endblocktranslate %}\n<!-- Good: Using blocktrans with other options -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktrans trimmed with book_t=book|title %} some value {% endblocktrans %}`} | ||
annotations={[]} | ||
lang="html" | ||
/> | ||
</TabItem> | ||
</Tabs> | ||
|
||
## Fail | ||
|
||
<Tabs | ||
groupId="config-language" | ||
defaultValue="toml" | ||
values={[ | ||
{ label: "TOML", value: "toml" }, | ||
{ label: "Shell", value: "shell" }, | ||
]} | ||
> | ||
<TabItem value="toml"> | ||
<CodeSnippet | ||
snippet={`<!-- Bad: Using blocktranslate without trimmed -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktranslate %} some value {% endblocktranslate %}\n<!-- Bad: Using blocktrans without trimmed -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktrans %} some value {% endblocktrans %}\n<!-- Bad: Using blocktranslate without trimmed but with other options -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktranslate count counter=list|length %} some value {% endblocktranslate %}\n<!-- Bad: Using blocktrans without trimmed but with other options -->\n<!-- django_block_translate_trimmed = true -->\n{% blocktrans with book_t=book|title %} some value {% endblocktrans %}\n\n`} | ||
annotations={[{"file": "test.html", "column": 1, "line": 3, "code": "django_block_translate_trimmed", "message": "`{% blocktranslate %}` must use the `trimmed` option"}, {"file": "test.html", "column": 1, "line": 6, "code": "django_block_translate_trimmed", "message": "`{% blocktrans %}` must use the `trimmed` option"}, {"file": "test.html", "column": 1, "line": 9, "code": "django_block_translate_trimmed", "message": "`{% blocktranslate count counter=list|length %}` must use the `trimmed` option"}, {"file": "test.html", "column": 1, "line": 12, "code": "django_block_translate_trimmed", "message": "`{% blocktrans with book_t=book|title %}` must use the `trimmed` option"}]} | ||
lang="html" | ||
/> | ||
</TabItem> | ||
<TabItem value="shell"> | ||
<CodeSnippet | ||
snippet={`<!-- Bad: Using blocktranslate without trimmed -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktranslate %} some value {% endblocktranslate %}\n<!-- Bad: Using blocktrans without trimmed -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktrans %} some value {% endblocktrans %}\n<!-- Bad: Using blocktranslate without trimmed but with other options -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktranslate count counter=list|length %} some value {% endblocktranslate %}\n<!-- Bad: Using blocktrans without trimmed but with other options -->\n<!-- curlylint --rule 'django_block_translate_trimmed: true' . -->\n{% blocktrans with book_t=book|title %} some value {% endblocktrans %}\n\n`} | ||
annotations={[{"file": "test.html", "column": 1, "line": 3, "code": "django_block_translate_trimmed", "message": "`{% blocktranslate %}` must use the `trimmed` option"}, {"file": "test.html", "column": 1, "line": 6, "code": "django_block_translate_trimmed", "message": "`{% blocktrans %}` must use the `trimmed` option"}, {"file": "test.html", "column": 1, "line": 9, "code": "django_block_translate_trimmed", "message": "`{% blocktranslate count counter=list|length %}` must use the `trimmed` option"}, {"file": "test.html", "column": 1, "line": 12, "code": "django_block_translate_trimmed", "message": "`{% blocktrans with book_t=book|title %}` must use the `trimmed` option"}]} | ||
lang="html" | ||
/> | ||
</TabItem> | ||
</Tabs> | ||
|
||
## Resources | ||
|
||
- [Django translations](https://docs.djangoproject.com/en/stable/topics/i18n/translation/) |
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