diff --git a/changelog_unreleased/handlebars/10958.md b/changelog_unreleased/handlebars/10958.md
new file mode 100644
index 000000000000..1890c5a7779e
--- /dev/null
+++ b/changelog_unreleased/handlebars/10958.md
@@ -0,0 +1,44 @@
+#### Preserve attributes order for element node (#10958 by @dcyriller)
+
+
+```handlebars
+{{!-- Input --}}
+
+{{!-- Prettier stable --}}
+
+{{!-- Prettier main --}}
+
+```
diff --git a/src/language-handlebars/printer-glimmer.js b/src/language-handlebars/printer-glimmer.js
index ded874597317..66e7ae6e0b1b 100644
--- a/src/language-handlebars/printer-glimmer.js
+++ b/src/language-handlebars/printer-glimmer.js
@@ -418,24 +418,30 @@ function print(path, options, print) {
/* ElementNode print helpers */
+function sortByLoc(a, b) {
+ return locStart(a) - locStart(b);
+}
+
function printStartingTag(path, print) {
const node = path.getValue();
- const attributesLike = ["attributes", "modifiers", "comments", "blockParams"]
- .filter((property) => isNonEmptyArray(node[property]))
- .map((property) => [
- line,
- property === "blockParams"
- ? printBlockParams(node)
- : join(line, path.map(print, property)),
- ]);
+ const types = ["attributes", "modifiers", "comments"].filter((property) =>
+ isNonEmptyArray(node[property])
+ );
+ const attributes = types.flatMap((type) => node[type]).sort(sortByLoc);
- return [
- "<",
- node.tag,
- indent(attributesLike),
- printStartingTagEndMarker(node),
- ];
+ for (const attributeType of types) {
+ path.each((attributePath) => {
+ const index = attributes.indexOf(attributePath.getValue());
+ attributes.splice(index, 1, [line, print()]);
+ }, attributeType);
+ }
+
+ if (isNonEmptyArray(node.blockParams)) {
+ attributes.push(line, printBlockParams(node));
+ }
+
+ return ["<", node.tag, indent(attributes), printStartingTagEndMarker(node)];
}
function printChildren(path, options, print) {
diff --git a/tests/format/handlebars/attr-node/__snapshots__/jsfmt.spec.js.snap b/tests/format/handlebars/attr-node/__snapshots__/jsfmt.spec.js.snap
index 525b90080aa0..0dd3610d00c3 100644
--- a/tests/format/handlebars/attr-node/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/handlebars/attr-node/__snapshots__/jsfmt.spec.js.snap
@@ -131,6 +131,41 @@ weirdly formatted
================================================================================
`;
+exports[`order.hbs format 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+
+
+=====================================output=====================================
+
+================================================================================
+`;
+
exports[`quotes.hbs format 1`] = `
====================================options=====================================
parsers: ["glimmer"]
diff --git a/tests/format/handlebars/attr-node/order.hbs b/tests/format/handlebars/attr-node/order.hbs
new file mode 100644
index 000000000000..f79a921b31a5
--- /dev/null
+++ b/tests/format/handlebars/attr-node/order.hbs
@@ -0,0 +1,12 @@
+