diff --git a/docs/src/demos/Extensions/TextAlign/index.vue b/docs/src/demos/Extensions/TextAlign/index.vue
index 58af3f46..25ddd3bf 100644
--- a/docs/src/demos/Extensions/TextAlign/index.vue
+++ b/docs/src/demos/Extensions/TextAlign/index.vue
@@ -9,6 +9,9 @@
+
diff --git a/packages/core/src/extensions/index.ts b/packages/core/src/extensions/index.ts
index d9006723..f21bbac3 100644
--- a/packages/core/src/extensions/index.ts
+++ b/packages/core/src/extensions/index.ts
@@ -11,6 +11,7 @@ export { RemoveMarks } from './removeMarks'
export { ScrollIntoView } from './scrollIntoView'
export { SelectAll } from './selectAll'
export { SelectParentNode } from './selectParentNode'
+export { SetDefaultNodeAttributes } from './setDefaultNodeAttributes'
export { SetNodeAttributes } from './setNodeAttributes'
export { SetBlockType } from './setBlockType'
export { SetContent } from './setContent'
diff --git a/packages/core/src/extensions/setDefaultNodeAttributes.ts b/packages/core/src/extensions/setDefaultNodeAttributes.ts
new file mode 100644
index 00000000..8347b141
--- /dev/null
+++ b/packages/core/src/extensions/setDefaultNodeAttributes.ts
@@ -0,0 +1,36 @@
+import { Command } from '../Editor'
+import { createExtension } from '../Extension'
+
+export const SetDefaultNodeAttributes = createExtension({
+ addCommands() {
+ return {
+ setDefaultNodeAttributes: (attributeNames: string[] = []): Command => ({ tr, state }) => {
+ const { selection } = tr
+ const { from, to } = selection
+
+ state.doc.nodesBetween(from, to, (node, pos) => {
+ if (!node.type.isText) {
+ attributeNames.forEach(name => {
+ const attribute = node.type.spec.attrs?.[name]
+ const defaultValue = attribute?.default
+
+ if (attribute && defaultValue !== undefined) {
+ tr.setNodeMarkup(pos, undefined, {
+ [name]: defaultValue,
+ })
+ }
+ })
+ }
+ })
+
+ return true
+ },
+ }
+ },
+})
+
+declare module '../Editor' {
+ interface AllExtensions {
+ SetDefaultNodeAttributes: typeof SetDefaultNodeAttributes,
+ }
+}