Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ options:
* xml-deprecated-qweb-directive

- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L7 Deprecated QWeb directive `t-esc-options`. Use `t-options` instead
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L37 Deprecated QWeb directive `t-field-options`. Use `t-options` instead
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L55 Deprecated QWeb directive `t-field-options`. Use `t-options` instead

* xml-deprecated-qweb-directive-15

Expand Down Expand Up @@ -523,14 +523,14 @@ options:

* xml-not-valid-char-link

- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L59 The resource in in src/href contains a not valid character
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L61 The resource in in src/href contains a not valid character
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L77 The resource in in src/href contains a not valid character
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L79 The resource in in src/href contains a not valid character

* xml-oe-structure-missing-id

- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L9 Consider removing the class `oe_structure` or adding a proper id to the tag. The id must contain `oe_structure`
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L13 Consider removing the class `oe_structure` or adding a proper id to the tag. The id must contain `oe_structure`
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L41 Consider removing the class `oe_structure` or adding a proper id to the tag. The id must contain `oe_structure`
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L59 Consider removing the class `oe_structure` or adding a proper id to the tag. The id must contain `oe_structure`

* xml-record-missing-id

Expand All @@ -543,16 +543,22 @@ options:
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/broken_module/model_view_odoo2.xml#L158 Redundant module name `<menuitem id="broken_module.menu_root"` Use `<menuitem id="menu_root"` instead
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/broken_module/model_view_odoo2.xml#L165 Redundant module name `<menuitem id="broken_module.menu_root2"` Use `<menuitem id="menu_root2"` instead

* xml-superfluous-attributeless

- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/broken_module/template1.xml#L30 Remove superfluous attributeless `<span` Serve no purpose and cause formatting inconsistencies with Prettier
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/broken_module/template1.xml#L34 Remove superfluous attributeless `<span` Serve no purpose and cause formatting inconsistencies with Prettier
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L60 Remove superfluous attributeless `<span` Serve no purpose and cause formatting inconsistencies with Prettier

* xml-syntax-error

- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/broken_module/file_no_exist.xml#L1 [Errno 2] No such file or directory: ''
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/broken_module/file_no_exist.xml#L1 [Errno 2] No such file or directory: ''

* xml-template-prettier-incompatible

- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L22 Node `<textarea ...><t t-out=...` incompatible for Prettier XML auto-fix. To prevent unexpected text insertion prefer `<textarea t-out=...`
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L24 Node `<textarea ...><t t-out=...` incompatible for Prettier XML auto-fix. To prevent unexpected text insertion prefer `<textarea t-out=...`
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L26 Node `<textarea ...><t t-out=...` incompatible for Prettier XML auto-fix. To prevent unexpected text insertion prefer `<textarea t-out=...`
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L22 Node `<textarea ...><t t-out=...` incompatible for Prettier XML auto-fix. To prevent unexpected text insertion prefer `<textarea t-out=...>` (move attribute to parent) or using 'style' attribute instead of tag e.g. <tag style="font-weight: bold">Black Text... instead of <b><tag...
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L24 Node `<textarea ...><t t-out=...` incompatible for Prettier XML auto-fix. To prevent unexpected text insertion prefer `<textarea t-out=...>` (move attribute to parent) or using 'style' attribute instead of tag e.g. <tag style="font-weight: bold">Black Text... instead of <b><tag...
- https://github.com/OCA/odoo-pre-commit-hooks/blob/v0.2.20/test_repo/test_module/website_templates.xml#L26 Node `<textarea ...><t t-out=...` incompatible for Prettier XML auto-fix. To prevent unexpected text insertion prefer `<textarea t-out=...>` (move attribute to parent) or using 'style' attribute instead of tag e.g. <tag style="font-weight: bold">Black Text... instead of <b><tag...

* xml-view-dangerous-replace-low-priority

Expand Down
85 changes: 64 additions & 21 deletions src/oca_pre_commit_hooks/checks_odoo_module_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,27 +633,49 @@ def verify_template_prettier_incompatible(self, template, manifest_data):
"""There are text tags incompatible with prettier xml autofix
More info https://github.com/OCA/odoo-pre-commit-hooks/issues/149"""
target_attrs = {"t-out", "t-esc", "t-raw"}
for node_textarea in template.xpath(".//textarea"):
if len(node_textarea_child := node_textarea.getchildren()) != 1:
continue
node_textarea_child = node_textarea_child[0]
has_text = node_textarea.text and node_textarea.text.strip()
has_tail = node_textarea_child.tail and node_textarea_child.tail.strip()
found_attr = set(node_textarea_child.attrib) & target_attrs
if node_textarea_child.tag != "t" or has_text or has_tail or not found_attr:
continue
found_attr = found_attr.pop()
self.register_error(
code="xml-template-prettier-incompatible",
message=(
f"Node `<{node_textarea.tag} ...><{node_textarea_child.tag} {found_attr}=...` "
"incompatible for Prettier XML auto-fix. To prevent unexpected text insertion "
f"prefer `<{node_textarea.tag} {found_attr}=...`"
),
filepath=manifest_data["filename_short"],
line=node_textarea_child.sourceline,
)
# TODO: Autofix using the same node
# Tags that wrap inline content and are affected by prettier formatting
inline_wrapper_tags = {"textarea", "b", "strong", "i", "em", "span", "a", "u", "s", "small", "mark"}

for wrapper_tag in inline_wrapper_tags:
for node_wrapper in template.xpath(f".//{wrapper_tag}"):
children = node_wrapper.getchildren()
if len(children) != 1:
continue

node_wrapper_child = children[0]

# Check if child has template attributes
found_attr = set(node_wrapper_child.attrib) & target_attrs
if not found_attr:
continue

# Only check for t or span tags with template attributes
if node_wrapper_child.tag not in ("t", "span"):
continue

# Check if wrapper has ONLY whitespace (or nothing) before the child
wrapper_text = node_wrapper.text or ""
has_meaningful_text = wrapper_text.strip()

# The problem occurs when:
# 1. There's a template attribute on the child
# 2. The wrapper has no meaningful text before the child (only whitespace/newlines)
# This means prettier will reformat and add unwanted newlines
if not has_meaningful_text:
found_attr = found_attr.pop()
self.register_error(
code="xml-template-prettier-incompatible",
message=(
f"Node `<{node_wrapper.tag} ...><{node_wrapper_child.tag} {found_attr}=...` "
"incompatible for Prettier XML auto-fix. To prevent unexpected text insertion "
f"prefer `<{node_wrapper.tag} {found_attr}=...>` (move attribute to parent) or "
"using 'style' attribute instead of tag "
'e.g. <tag style="font-weight: bold">Black Text... instead of <b><tag...'
),
filepath=manifest_data["filename_short"],
line=node_wrapper_child.sourceline,
)
# TODO: Autofix using the same node

def has_escaped_double_quotes(self, filename) -> bool:
"""Check if filename contains escaped double quotes " -> &quot;
Expand Down Expand Up @@ -765,6 +787,7 @@ def check_xml_double_quotes_py(self):
"xml-dangerous-qweb-replace-low-priority",
"xml-duplicate-template-id",
"xml-id-position-first",
"xml-superfluous-attributeless",
"xml-template-prettier-incompatible",
)
def check_xml_templates(self):
Expand All @@ -778,6 +801,7 @@ def check_xml_templates(self):
Indentify nodes incompatible with Prettier XML auto-fix generating possible unexpected text insertion
"""
template_ids: Dict[str, List[FileElementPair]] = defaultdict(list)
pattern = re.compile(rb"<span>(.*?)</span>")
for manifest_data in self.manifest_datas:
for template in self.xpath_template(manifest_data["node"]):
if self.is_message_enabled(
Expand All @@ -789,6 +813,25 @@ def check_xml_templates(self):
if not template_id: # pragma: no cover
continue
template_ids[template_id].append(FileElementPair(manifest_data["filename_short"], template))
if self.is_message_enabled("xml-superfluous-attributeless", manifest_data["disabled_checks"]):
for node_attrless in template.xpath(".//span[not(@*)]"):
self.register_error(
code="xml-superfluous-attributeless",
message=f"Remove superfluous attributeless `<{node_attrless.tag}`",
info=f"Serve no purpose and cause formatting inconsistencies with Prettier",
filepath=manifest_data["filename_short"],
line=node_attrless.sourceline,
)
if self.autofix:
node_content = node_xml.NodeContent(manifest_data["filename"], node_attrless)
new_content_node = pattern.sub(rb"\1", node_content.content_node, count=1)
if new_content_node != node_content.content_node:
# Modify the record attrib to propagate the change to other checks
node_content.content_node = new_content_node
utils.perform_fix(manifest_data["filename"], bytes(node_content))
# TODO: check if the "for" affects updating the nodes
self.update_node(manifest_data) # update sourceline after delete a node

if self.is_message_enabled("xml-template-prettier-incompatible", manifest_data["disabled_checks"]):
self.verify_template_prettier_incompatible(template, manifest_data)

Expand Down
18 changes: 18 additions & 0 deletions test_repo/test_module/website_templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@
<textarea name="fixed" t-out="campaign.description" />
<!--prettier compatible-->
<textarea name="mixed"> Ver: <t t-out="campaign.url" /></textarea>
<!--prettier compatible-->
<div>
<div class="page">
Dear
<b>
<span t-out="partner_name or ''" />
</b>:<br />
By this means, you are informed that the budget movement of
<span t-out="move_type" />
with the number:
<b>
<span t-out="move_name" />
</b>
has been liquidated and transferred
to the available balance of the related budgetary item.<br />
Regards,
</div>
</div>
</template>

<!-- Deprecated QWeb directive "t-field-options". -->
Expand Down
3 changes: 2 additions & 1 deletion tests/test_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"xml-not-valid-char-link": 2,
"xml-redundant-module-name": 3,
"xml-syntax-error": 2,
"xml-template-prettier-incompatible": 3,
"xml-template-prettier-incompatible": 5,
"xml-view-dangerous-replace-low-priority": 7,
"xml-xpath-translatable-item": 4,
"xml-oe-structure-missing-id": 6,
Expand All @@ -56,6 +56,7 @@
"xml-deprecated-oe-chatter": 1,
"xml-field-bool-without-eval": 2,
"xml-field-numeric-without-eval": 7,
"xml-superfluous-attributeless": 5,
}


Expand Down
Loading