diff --git a/module_instructions.module b/module_instructions.module
index 5cddeef..0385ffd 100644
--- a/module_instructions.module
+++ b/module_instructions.module
@@ -4,7 +4,8 @@
  * @file
  * Contains module_instructions.module.
  */
-
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\module_instructions\Hook\ModuleInstructionsHooks;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
@@ -12,64 +13,26 @@ use Drupal\Core\Url;
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function module_instructions_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    case 'help.page.module_instructions':
-      $output = '';
-      $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('Module Instructions module shows the content of README.txt, CHANGELOG.txt and LICENSE.txt files for contrib modules.') . '</p>';
-      return $output;
-  }
+  return \Drupal::service(ModuleInstructionsHooks::class)->help($route_name, $route_match);
 }
 
 /**
  * Implements hook_module_instructions_info().
  */
+#[LegacyHook]
 function module_instructions_module_instructions_info() {
-  return [
-    'readme' => [
-      'label' => t('Readme'),
-    ],
-    'license' => [
-      'label' => t('License'),
-    ],
-    'changelog' => [
-      'label' => t('Changelog'),
-    ],
-  ];
+  return \Drupal::service(ModuleInstructionsHooks::class)->moduleInstructionsInfo();
 }
 
 /**
  * Implements hook_form_FORM_ID_alter().
  */
-function module_instructions_form_system_modules_alter(&$form, FormStateInterface $form_state, $form_id) {
-  if (!\Drupal::currentUser()->hasPermission('access module instruction files')) {
-    return;
-  }
-
-  /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
-  $module_handler = \Drupal::service('module_handler');
-  $files = $module_handler->invokeAll('module_instructions_info');
-
-  /** @var \Drupal\Core\Config\ImmutableConfig $config */
-  $config = \Drupal::config('module_instructions.settings');
-  $types = $config->get('types');
-
-  $collection = \Drupal::state()->get('module_instructions_collection');
-  foreach ($form['modules'] as $name => $group) {
-    if (is_array($group)) {
-      foreach ($group as $module => $item) {
-        if (is_array($item) && !empty($item['name']) && !empty($collection[$module])) {
-          foreach ($collection[$module] as $type => $file) {
-            if ($collection[$module][$type] && isset($types[$type])) {
-              $label = !empty($files[$type]['label']) ? $files[$type]['label'] : ucfirst($type);
-              $form['modules'][$name][$module]['links'][$type] = _module_instructions_create_link_array($module, $label, $file);
-            }
-          }
-        }
-      }
-    }
-  }
+#[LegacyHook]
+function module_instructions_form_system_modules_alter(&$form, FormStateInterface $form_state, $form_id)
+{
+    \Drupal::service(ModuleInstructionsHooks::class)->formSystemModulesAlter($form, $form_state, $form_id);
 }
 
 /**
@@ -107,83 +70,45 @@ function _module_instructions_create_link_array($module, $label, $file) {
 /**
  * Implements hook_theme_registry_alter().
  */
+#[LegacyHook]
 function module_instructions_theme_registry_alter(&$theme_registry) {
-  if (!empty($theme_registry['system_modules_details']) &&
-    \Drupal::currentUser()->hasPermission('access module instruction files')
-  ) {
-    $path = \Drupal::service('extension.path.resolver')->getPath('module', 'module_instructions') . '/templates';
-    $theme_registry['system_modules_details']['path'] = $path;
-  }
+  \Drupal::service(ModuleInstructionsHooks::class)->themeRegistryAlter($theme_registry);
 }
 
 /**
  * Implements hook_preprocess_HOOK().
  */
-function module_instructions_preprocess_system_modules_details(&$variables) {
-  /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
-  $module_handler = \Drupal::service('module_handler');
-  $files = $module_handler->invokeAll('module_instructions_info');
-
-  $variables['module_links'] = array_merge(['help', 'permissions', 'configure'], array_keys($files));
+#[LegacyHook]
+function module_instructions_preprocess_system_modules_details(&$variables)
+{
+    \Drupal::service(ModuleInstructionsHooks::class)->preprocessSystemModulesDetails($variables);
 }
 
 /**
  * Implements hook_cron().
  */
-function module_instructions_cron() {
-  /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
-  $module_handler = \Drupal::service('module_handler');
-  $modules = $module_handler->getModuleList();
-
-  // Get all files.
-  $files = $module_handler->invokeAll('module_instructions_info');
-
-  $collection = [];
-  foreach ($modules as $module => $info) {
-    $collection[$module] = [];
-
-    foreach ($files as $file => $data) {
-      $collection[$module][strtolower($file)] = module_instructions_file_exists($module, $file);
-    }
-  }
-
-  \Drupal::state()->set('module_instructions_collection', $collection);
+#[LegacyHook]
+function module_instructions_cron()
+{
+    \Drupal::service(ModuleInstructionsHooks::class)->cron();
 }
 
 /**
  * Implements hook_modules_installed().
  */
-function module_instructions_modules_installed($modules, $is_syncing) {
-  $collection = \Drupal::state()->get('module_instructions_collection');
-
-  /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
-  $module_handler = \Drupal::service('module_handler');
-  $files = $module_handler->invokeAll('module_instructions_info');
-
-  foreach ($modules as $module) {
-    $collection[$module] = [];
-
-    foreach ($files as $file => $data) {
-      $collection[$module][strtolower($file)] = module_instructions_file_exists($module, $file);
-    }
-  }
-
-  \Drupal::state()->set('module_instructions_collection', $collection);
+#[LegacyHook]
+function module_instructions_modules_installed($modules, $is_syncing)
+{
+    \Drupal::service(ModuleInstructionsHooks::class)->modulesInstalled($modules, $is_syncing);
 }
 
 /**
  * Implements hook_modules_uninstalled().
  */
-function module_instructions_modules_uninstalled($modules, $is_syncing) {
-  $collection = \Drupal::state()->get('module_instructions_collection');
-
-  foreach ($modules as $module) {
-    if (isset($collection[$module])) {
-      unset($collection[$module]);
-    }
-  }
-
-  \Drupal::state()->set('module_instructions_collection', $collection);
+#[LegacyHook]
+function module_instructions_modules_uninstalled($modules, $is_syncing)
+{
+    \Drupal::service(ModuleInstructionsHooks::class)->modulesUninstalled($modules, $is_syncing);
 }
 
 /**
diff --git a/module_instructions.services.yml b/module_instructions.services.yml
new file mode 100644
index 0000000..df26e49
--- /dev/null
+++ b/module_instructions.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\module_instructions\Hook\ModuleInstructionsHooks:
+    class: Drupal\module_instructions\Hook\ModuleInstructionsHooks
+    autowire: true
diff --git a/src/Controller/ModuleInstructionsController.php b/src/Controller/ModuleInstructionsController.php
index 7ced161..07109ed 100644
--- a/src/Controller/ModuleInstructionsController.php
+++ b/src/Controller/ModuleInstructionsController.php
@@ -79,7 +79,7 @@ class ModuleInstructionsController extends ControllerBase {
       $this->moduleHandler->alter('module_instructions_pre_view', $content, $context);
 
       return [
-        '#markup' => '<pre>' . check_markup(_filter_url($content, $filter), $context['format']) . '</pre>',
+        '#markup' => '<pre>' . ['#type' => 'processed_text', '#text' => _filter_url($content, $filter), '#format' => $context['format']] . '</pre>',
       ];
     }
 
diff --git a/src/Hook/ModuleInstructionsHooks.php b/src/Hook/ModuleInstructionsHooks.php
new file mode 100644
index 0000000..cd97098
--- /dev/null
+++ b/src/Hook/ModuleInstructionsHooks.php
@@ -0,0 +1,160 @@
+<?php
+
+namespace Drupal\module_instructions\Hook;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Url;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+/**
+ * Hook implementations for module_instructions.
+ */
+class ModuleInstructionsHooks
+{
+    use StringTranslationTrait;
+    /**
+     * Implements hook_help().
+     */
+    #[Hook('help')]
+    public function help($route_name, \Drupal\Core\Routing\RouteMatchInterface $route_match)
+    {
+        switch ($route_name) {
+            case 'help.page.module_instructions':
+                $output = '';
+                $output .= '<h3>' . $this->t('About') . '</h3>';
+                $output .= '<p>' . $this->t('Module Instructions module shows the content of README.txt, CHANGELOG.txt and LICENSE.txt files for contrib modules.') . '</p>';
+                return $output;
+        }
+    }
+    /**
+     * Implements hook_module_instructions_info().
+     */
+    #[Hook('module_instructions_info')]
+    public function moduleInstructionsInfo()
+    {
+        return [
+            'readme' => [
+                'label' => $this->t('Readme'),
+            ],
+            'license' => [
+                'label' => $this->t('License'),
+            ],
+            'changelog' => [
+                'label' => $this->t('Changelog'),
+            ],
+        ];
+    }
+    /**
+     * Implements hook_form_FORM_ID_alter().
+     */
+    #[Hook('form_system_modules_alter')]
+    public static function formSystemModulesAlter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
+    {
+        if (!\Drupal::currentUser()->hasPermission('access module instruction files')) {
+            return;
+        }
+        /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
+        $module_handler = \Drupal::service('module_handler');
+        $files = $module_handler->invokeAll('module_instructions_info');
+        /** @var \Drupal\Core\Config\ImmutableConfig $config */
+        $config = \Drupal::config('module_instructions.settings');
+        $types = $config->get('types');
+        $collection = \Drupal::state()->get('module_instructions_collection');
+        foreach ($form['modules'] as $name => $group) {
+            if (is_array($group)) {
+                foreach ($group as $module => $item) {
+                    if (is_array($item) && !empty($item['name']) && !empty($collection[$module])) {
+                        foreach ($collection[$module] as $type => $file) {
+                            if ($collection[$module][$type] && isset($types[$type])) {
+                                $label = !empty($files[$type]['label']) ? $files[$type]['label'] : ucfirst($type);
+                                $form['modules'][$name][$module]['links'][$type] = _module_instructions_create_link_array($module, $label, $file);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    /**
+     * Implements hook_theme_registry_alter().
+     */
+    #[Hook('theme_registry_alter')]
+    public static function themeRegistryAlter(&$theme_registry)
+    {
+        if (!empty($theme_registry['system_modules_details']) && \Drupal::currentUser()->hasPermission('access module instruction files')) {
+            $path = \Drupal::service('extension.path.resolver')->getPath('module', 'module_instructions') . '/templates';
+            $theme_registry['system_modules_details']['path'] = $path;
+        }
+    }
+    /**
+     * Implements hook_preprocess_HOOK().
+     */
+    #[Hook('preprocess_system_modules_details')]
+    public static function preprocessSystemModulesDetails(&$variables)
+    {
+        /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
+        $module_handler = \Drupal::service('module_handler');
+        $files = $module_handler->invokeAll('module_instructions_info');
+        $variables['module_links'] = array_merge([
+            'help',
+            'permissions',
+            'configure',
+        ], array_keys($files));
+    }
+    /**
+     * Implements hook_cron().
+     */
+    #[Hook('cron')]
+    public static function cron()
+    {
+        /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
+        $module_handler = \Drupal::service('module_handler');
+        $modules = $module_handler->getModuleList();
+        // Get all files.
+        $files = $module_handler->invokeAll('module_instructions_info');
+        $collection = [
+        ];
+        foreach ($modules as $module => $info) {
+            $collection[$module] = [
+            ];
+            foreach ($files as $file => $data) {
+                $collection[$module][strtolower($file)] = module_instructions_file_exists($module, $file);
+            }
+        }
+        \Drupal::state()->set('module_instructions_collection', $collection);
+    }
+    /**
+     * Implements hook_modules_installed().
+     */
+    #[Hook('modules_installed')]
+    public static function modulesInstalled($modules, $is_syncing)
+    {
+        $collection = \Drupal::state()->get('module_instructions_collection');
+        /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
+        $module_handler = \Drupal::service('module_handler');
+        $files = $module_handler->invokeAll('module_instructions_info');
+        foreach ($modules as $module) {
+            $collection[$module] = [
+            ];
+            foreach ($files as $file => $data) {
+                $collection[$module][strtolower($file)] = module_instructions_file_exists($module, $file);
+            }
+        }
+        \Drupal::state()->set('module_instructions_collection', $collection);
+    }
+    /**
+     * Implements hook_modules_uninstalled().
+     */
+    #[Hook('modules_uninstalled')]
+    public static function modulesUninstalled($modules, $is_syncing)
+    {
+        $collection = \Drupal::state()->get('module_instructions_collection');
+        foreach ($modules as $module) {
+            if (isset($collection[$module])) {
+                unset($collection[$module]);
+            }
+        }
+        \Drupal::state()->set('module_instructions_collection', $collection);
+    }
+}
