diff --git a/modules/file_attachment/markdownify_file_attachment.module b/modules/file_attachment/markdownify_file_attachment.module
index b2ea999d44f0f0fb31bdcba088f52afa0c75eec7..b121d7cbe858f59598e041e20c5bd130721a3964 100644
--- a/modules/file_attachment/markdownify_file_attachment.module
+++ b/modules/file_attachment/markdownify_file_attachment.module
@@ -10,78 +10,37 @@ declare(strict_types=1);
 use Drupal\Component\Utility\Bytes;
 use Drupal\Component\Utility\Environment;
 use Drupal\Core\Entity\FieldableEntityInterface;
-use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
 use Drupal\Core\Render\BubbleableMetadata;
-use Drupal\file\FileInterface;
 
 /**
- * Implements hook_markdownify_entity_html_alter().
+ * Implements hook_markdownify_entity_build_alter().
+ *
+ * Ensures entity reference fields pointing to files are rendered using the
+ * "md_file_attachment_file_embed" formatter when the format is Markdown.
  */
-function markdownify_file_attachment_markdownify_entity_html_alter(string &$html, array $context, ?BubbleableMetadata $metadata): void {
+function markdownify_file_attachment_markdownify_entity_build_alter(array &$build, array $context, ?BubbleableMetadata $metadata): void {
   $entity = $context['entity'] ?? NULL;
   if (!$entity instanceof FieldableEntityInterface) {
     return;
   }
-
-  $file_attachment_lines = [];
-  $config = \Drupal::config('markdownify_file_attachment.settings');
-  $allowed_extensions = $config->get('allowed_extensions');
-  $max_file_embed_size = min(Bytes::toNumber($config->get('max_file_embed_size') ?? 0), Environment::getUploadMaxSize());
-
-  foreach ($entity->getFields() as $field) {
-    // Skip fields that not file reference fields.
-    if (!$field instanceof EntityReferenceFieldItemListInterface || $field->isEmpty()) {
-      continue;
-    }
-    if (($field->getFieldDefinition()->getFieldStorageDefinition()->getSetting('target_type') ?? '') !== 'file') {
-      continue;
-    }
-
-    foreach ($field->referencedEntities() as $file) {
-      assert($file instanceof FileInterface);
-
-      $access_result = $file->access('view', Drupal::currentUser(), TRUE);
-      $metadata->addCacheableDependency($access_result);
-
-      if (!$access_result->isAllowed()) {
-        continue;
-      }
-
-      $filename = $file->getFilename();
-      $filesize = $file->getSize();
-      $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
-      $uri = $file->getFileUri();
-      $url = \Drupal::service('file_url_generator')->generateAbsoluteString($uri);
-
-      if (in_array($extension, $allowed_extensions, TRUE) && $filesize <= $max_file_embed_size) {
-        $real_path = \Drupal::service('file_system')->realpath($uri);
-        if (is_readable($real_path)) {
-          $content = @file_get_contents($real_path);
-          $line = "Attached file {$filename} with {$extension} extension available at {$url} follows:\n";
-          $line .= <<<EOD
-          ```
-          {$content}
-          ```
-          EOD;
-          $file_attachment_lines[] = $line;
-        }
-      }
-      else {
-        $file_attachment_lines[] = "Attached file {$filename} with {$extension} extension is available at {$url}.";
+  foreach ($entity->getFieldDefinitions() as $field) {
+    $field_name = $field->getName();
+    if ($field->getType() === 'file') {
+      $config = \Drupal::config('markdownify_file_attachment.settings');
+      $display_options = [
+        'type' => 'md_file_attachment_file_embed',
+        'settings' => [
+          'allowed_extensions' => $config->get('allowed_extensions'),
+          'max_size' => min(Bytes::toNumber($config->get('max_file_embed_size') ?? 0), Environment::getUploadMaxSize()),
+        ],
+      ];
+      $field_name = $field->getName();
+      $field_build = $entity->get($field_name)->view($display_options);
+      $build[$field_name] = $field_build;
+      if ($metadata) {
+        $cacheability = BubbleableMetadata::createFromRenderArray($field_build);
+        $metadata->merge($cacheability);
       }
     }
   }
-
-  /** @var \Drupal\Core\Render\RendererInterface $renderer */
-  $renderer = \Drupal::service('renderer');
-  if ($renderer->hasRenderContext()) {
-    $build = [];
-    $metadata->applyTo($build);
-    $renderer->render($build);
-  }
-
-  if ($file_attachment_lines !== []) {
-    $html .= nl2br("\n" . implode("\n\n", $file_attachment_lines));
-  }
-
 }
diff --git a/modules/file_attachment/src/Plugin/Field/FieldFormatter/MdFileAttachmentFieldFormatter.php b/modules/file_attachment/src/Plugin/Field/FieldFormatter/MdFileAttachmentFieldFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..689296a4f26d162ed08ec2a635415572c1406fc3
--- /dev/null
+++ b/modules/file_attachment/src/Plugin/Field/FieldFormatter/MdFileAttachmentFieldFormatter.php
@@ -0,0 +1,152 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\markdownify_file_attachment\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\File\FileSystemInterface;
+use Drupal\Core\File\FileUrlGeneratorInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Render\RenderContext;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\file\Plugin\Field\FieldFormatter\FileFormatterBase;
+use Drupal\file\Plugin\Field\FieldType\FileFieldItemList;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Plugin implementation of the 'entity_reference_file_attachment' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "md_file_attachment_file_embed",
+ *   label = @Translation("Embed file as Markdown"),
+ *   field_types = {
+ *     "file"
+ *   }
+ * )
+ */
+final class MdFileAttachmentFieldFormatter extends FileFormatterBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * File URL generator.
+   *
+   * @var \Drupal\Core\File\FileUrlGeneratorInterface
+   */
+  private FileUrlGeneratorInterface $fileUrlGenerator;
+
+  /**
+   * Renderer interface.
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  private RendererInterface $renderer;
+
+  /**
+   * Logger interface.
+   *
+   * @var \Psr\Log\LoggerInterface
+   */
+  private LoggerInterface $logger;
+
+  /**
+   * File system interface.
+   *
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  private FileSystemInterface $fileSystem;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
+    $instance = new self(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['label'],
+      $configuration['view_mode'],
+      $configuration['third_party_settings'],
+    );
+
+    $instance->fileUrlGenerator = $container->get('file_url_generator');
+    $instance->renderer = $container->get('renderer');
+    $instance->logger = $container->get('logger.channel.markdownify');
+    $instance->fileSystem = $container->get('file_system');
+
+    return $instance;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings(): array {
+    return [
+      'allowed_extensions' => ['yml', 'txt'],
+      'max_size' => 1024,
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items, $langcode): array {
+    assert($items instanceof FileFieldItemList);
+    $element = [];
+
+    $allowed_extensions = $this->getSetting('allowed_extensions');
+    $max_size = $this->getSetting('max_size');
+
+    foreach ($this->getEntitiesToView($items, $langcode) as $delta => $file) {
+
+      if (!$file) {
+        continue;
+      }
+
+      $file_size = $file->getSize();
+      $file_name = $file->getFilename();
+      $extension = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
+      $uri = $file->getFileUri();
+      $url = '';
+      try {
+        $context = new RenderContext();
+        $url = $this->renderer->executeInRenderContext($context, function () use ($uri) {
+          return $this->fileUrlGenerator->generateAbsoluteString($uri);
+        });
+      }
+      catch (\Exception $e) {
+        $this->logger->error('Failed to render file URL: @message', ['@message' => $e->getMessage()]);
+      }
+
+      $real_path = $this->fileSystem->realpath($uri);
+
+      if (in_array($extension, $allowed_extensions, TRUE) && $file_size <= $max_size) {
+        $content = @file_get_contents($real_path);
+        $element[$delta] = [
+          '#type' => 'markup',
+          '#markup' => $this->t('Attached file %filename with %extension extension available at %url follows:<br>%file', [
+            '%filename' => $file_name,
+            '%extension' => $extension,
+            '%file' => $content,
+            '%url' => $url,
+          ]),
+        ];
+      }
+      else {
+        $element[$delta] = [
+          '#type' => 'markup',
+          '#markup' => $this->t('Attached file %filename with %extension extension available at %url', [
+            '%filename' => $file_name,
+            '%extension' => $extension,
+            '%url' => $url,
+          ]),
+        ];
+      }
+
+    }
+
+    return $element;
+  }
+
+}