diff --git a/composer.json b/composer.json
index 97c8aa6d698460d4a3c36e205cd4ccbf8e1c73d2..9b8fa8c6304ba73949d74676d65e2fb13e35ca6e 100644
--- a/composer.json
+++ b/composer.json
@@ -8,35 +8,35 @@
             "url": "https://packages.drupal.org/8"
         },
         {
-          "type": "package",
-          "package": {
-              "name": "browserstate/history.js",
-              "version": "1.8.0",
-              "type": "drupal-library",
-              "source": {
-                  "url": "https://github.com/browserstate/history.js",
-                  "type": "git",
-                  "reference": "origin/master"
-              }
-          }
+            "type": "package",
+            "package": {
+                "name": "browserstate/history.js",
+                "version": "1.8.0",
+                "type": "drupal-library",
+                "source": {
+                    "url": "https://github.com/browserstate/history.js",
+                    "type": "git",
+                    "reference": "origin/master"
+                }
+            }
         },
         {
-          "type": "package",
-          "package": {
-              "name": "ckeditor/indentblock",
-              "version": "4.8.0",
-              "type": "drupal-library",
-              "extra": {
-                  "installer-name": "indentblock"
-              },
-              "dist": {
-                  "url": "https://download.ckeditor.com/indentblock/releases/indentblock_4.8.0.zip",
-                  "type": "zip"
-              },
-              "require": {
-                  "composer/installers": "~1.0"
-              }
-          }
+            "type": "package",
+            "package": {
+                "name": "ckeditor/indentblock",
+                "version": "4.8.0",
+                "type": "drupal-library",
+                "extra": {
+                    "installer-name": "indentblock"
+                },
+                "dist": {
+                    "url": "https://download.ckeditor.com/indentblock/releases/indentblock_4.8.0.zip",
+                    "type": "zip"
+                },
+                "require": {
+                    "composer/installers": "~1.0"
+                }
+            }
         },
         {
             "type": "package",
@@ -52,16 +52,16 @@
             }
         },
         {
-          "type": "package",
-          "package": {
-              "name": "desandro/masonry",
-              "version": "4.2.0",
-              "type": "drupal-library",
-              "dist": {
-                  "url": "https://github.com/desandro/masonry/archive/v4.2.0.zip",
-                  "type": "zip"
-              }
-          }
+            "type": "package",
+            "package": {
+                "name": "desandro/masonry",
+                "version": "4.2.0",
+                "type": "drupal-library",
+                "dist": {
+                    "url": "https://github.com/desandro/masonry/archive/v4.2.0.zip",
+                    "type": "zip"
+                }
+            }
         },
         {
             "type": "package",
@@ -241,17 +241,17 @@
         "drupal-scaffold": {
             "source": "https://raw.githubusercontent.com/pantheon-systems/drops-8-scaffolding/{version}/{path}",
             "locations": {
-              "web-root": "web/"
+                "web-root": "web/"
             },
             "file-mapping": {
-              "[web-root]/INSTALL.txt": false,
-              "[web-root]/README.txt": false,
-              "[web-root]/example.gitignore": false,
-              "[web-root]/modules/README.txt": false,
-              "[web-root]/profiles/README.txt": false,
-              "[web-root]/sites/README.txt": false,
-              "[web-root]/themes/README.txt": false,
-              "[web-root]/web.config": false
+                "[web-root]/INSTALL.txt": false,
+                "[web-root]/README.txt": false,
+                "[web-root]/example.gitignore": false,
+                "[web-root]/modules/README.txt": false,
+                "[web-root]/profiles/README.txt": false,
+                "[web-root]/sites/README.txt": false,
+                "[web-root]/themes/README.txt": false,
+                "[web-root]/web.config": false
             }
         },
         "patches": {
@@ -270,10 +270,10 @@
                 "2811189": "https://www.drupal.org/files/issues/2019-08-08/honeypot_field_weight_2811189-18.patch"
             },
             "drupal/inline_entity_form": {
-              "3208279": "https://www.drupal.org/files/issues/2021-05-08/inline_entity_form-n3208279-13.patch"
+                "3208279": "https://www.drupal.org/files/issues/2021-05-08/inline_entity_form-n3208279-13.patch"
             },
             "drupal/linkit": {
-                "2712951": "https://www.drupal.org/files/issues/2019-11-27/linkit_for_link_field-2712951-140.patch"
+                "2712951": "https://www.drupal.org/files/issues/2021-04-07/linkit-for-link-field-2712951-216.patch"
             },
             "drupal/multiple_fields_remove_button": {
                 "Adding Date Range": "patches/multiple_fields_remove_button-daterange-addition.patch"
@@ -297,4 +297,4 @@
             "php": "7.3"
         }
     }
-}
+}
\ No newline at end of file
diff --git a/composer.lock b/composer.lock
index 8c56468a3d229e92ed52dc7cda106128c1731dfb..a6998f9407383128cfe3cd6be3baee4d12c68aa9 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "57672c9e8b696e724095b806e2f77021",
+    "content-hash": "b66a2b43b306587d15fdf11ea2858c8e",
     "packages": [
         {
             "name": "alchemy/zippy",
diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php
index 17e2162afed14560c5ce505052a68615faf8e6b9..d10cf1dfe638af1c3084458ed964d208e446c1b7 100644
--- a/vendor/composer/InstalledVersions.php
+++ b/vendor/composer/InstalledVersions.php
@@ -32,7 +32,7 @@ class InstalledVersions
     'aliases' => 
     array (
     ),
-    'reference' => '0f8a8ac02e1ff090c2405d8b83248b5f4f75856b',
+    'reference' => 'a971e84acff6246067d76e462156e6664731e864',
     'name' => 'osu-asc-webservices/d8-upstream',
   ),
   'versions' => 
@@ -2262,7 +2262,7 @@ class InstalledVersions
       'aliases' => 
       array (
       ),
-      'reference' => '0f8a8ac02e1ff090c2405d8b83248b5f4f75856b',
+      'reference' => 'a971e84acff6246067d76e462156e6664731e864',
     ),
     'pantheon-systems/quicksilver-pushback' => 
     array (
@@ -3281,8 +3281,11 @@ public static function getRootPackage()
 
 
 
+
 public static function getRawData()
 {
+@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
 return self::$installed;
 }
 
@@ -3292,6 +3295,17 @@ public static function getRawData()
 
 
 
+public static function getAllRawData()
+{
+return self::getInstalled();
+}
+
+
+
+
+
+
+
 
 
 
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index b15055f50a27c47d987d5b01b5c8a38ab479dd46..4d3c1db90ad69f89b5c3a45bc5be757306f418a2 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -5513,7 +5513,7 @@
                     }
                 },
                 "patches_applied": {
-                    "2712951": "https://www.drupal.org/files/issues/2019-11-27/linkit_for_link_field-2712951-140.patch"
+                    "2712951": "https://www.drupal.org/files/issues/2021-04-07/linkit-for-link-field-2712951-216.patch"
                 }
             },
             "installation-source": "dist",
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 447187c225e90628dc08014de6f557344ecf0f38..3616e8059dec3af568f6a1a8b21c7261b86c3851 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -6,7 +6,7 @@
     'aliases' => 
     array (
     ),
-    'reference' => '0f8a8ac02e1ff090c2405d8b83248b5f4f75856b',
+    'reference' => 'a971e84acff6246067d76e462156e6664731e864',
     'name' => 'osu-asc-webservices/d8-upstream',
   ),
   'versions' => 
@@ -2236,7 +2236,7 @@
       'aliases' => 
       array (
       ),
-      'reference' => '0f8a8ac02e1ff090c2405d8b83248b5f4f75856b',
+      'reference' => 'a971e84acff6246067d76e462156e6664731e864',
     ),
     'pantheon-systems/quicksilver-pushback' => 
     array (
diff --git a/web/modules/custom/customtokens/customtokens.module b/web/modules/custom/customtokens/customtokens.module
index 0ea9b6de2940c6c6f2d189ca13a91ae451dd0289..4cd9cfcf9975b60823cd42a902402327ec03e4bf 100644
--- a/web/modules/custom/customtokens/customtokens.module
+++ b/web/modules/custom/customtokens/customtokens.module
@@ -29,12 +29,12 @@ function customtokens_tokens($type, $tokens, array $data, array $options, \Drupa
     //research ct
     $nids = \Drupal::entityQuery('node')->condition('type','research_landing_page')->execute();
     $lid = array_shift($nids);
-    $alias = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$lid);
+    $alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/'.$lid);
 
     //research gallery ct
     $nids2 = \Drupal::entityQuery('node')->condition('type','research_gallery_landing_page')->execute();
     $lid2 = array_shift($nids2);
-    $alias2 = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$lid2);
+    $alias2 = \Drupal::service('path_alias.manager')->getAliasByPath('/node/'.$lid2);
 
 
     if ($type == 'customtoken' && !empty($data['node'])) {
diff --git a/web/modules/linkit/PATCHES.txt b/web/modules/linkit/PATCHES.txt
index 2c2692ba419ab1ae53ae6423c71d699d21bbbad6..ad45756bcc49243ecb529af58a6e4b22ca371ea8 100644
--- a/web/modules/linkit/PATCHES.txt
+++ b/web/modules/linkit/PATCHES.txt
@@ -2,6 +2,6 @@ This file was automatically generated by Composer Patches (https://github.com/cw
 Patches applied to this directory:
 
 2712951
-Source: https://www.drupal.org/files/issues/2019-11-27/linkit_for_link_field-2712951-140.patch
+Source: https://www.drupal.org/files/issues/2021-04-07/linkit-for-link-field-2712951-216.patch
 
 
diff --git a/web/modules/linkit/config/schema/linkit.schema.yml b/web/modules/linkit/config/schema/linkit.schema.yml
index b8d487cbd0d1851e115a1b30dd5ddec1ddb2ac7e..3787e95c9abca4a8bcac582ee501287bca102c0f 100644
--- a/web/modules/linkit/config/schema/linkit.schema.yml
+++ b/web/modules/linkit/config/schema/linkit.schema.yml
@@ -121,6 +121,9 @@ field.widget.settings.linkit:
     linkit_profile:
       type: string
       label: 'Linkit profile'
+    linkit_auto_link_text:
+      type: boolean
+      label: 'Automatically populate link text from entity label'
 
 # Schema for the Linkit formatter.
 field.formatter.settings.linkit:
diff --git a/web/modules/linkit/js/linkit.autocomplete.js b/web/modules/linkit/js/linkit.autocomplete.js
index b2ccca311d0b6a330fbd650a2ee2d27c40c70065..8ef722fe6000569b1f114281f85fa40064248cb5 100644
--- a/web/modules/linkit/js/linkit.autocomplete.js
+++ b/web/modules/linkit/js/linkit.autocomplete.js
@@ -83,7 +83,7 @@
 
     if (ui.item.label) {
       // Automatically set the link title.
-      var $linkTitle = $(event.target).closest('.form-item').siblings('.form-type-textfield').find('.linkit-widget-title');
+      var $linkTitle = $('.linkit-widget-title--autofill-enabled', $context);
       if ($linkTitle.length > 0) {
         if (!$linkTitle.val() || $linkTitle.hasClass('link-widget-title--auto')) {
           // Set value to the label.
diff --git a/web/modules/linkit/src/Plugin/Field/FieldFormatter/LinkitFormatter.php b/web/modules/linkit/src/Plugin/Field/FieldFormatter/LinkitFormatter.php
index 775da51423b9a224168f660d9a9b15d035c9055b..c1070349b7f980a706c4a7a09346f417cedc9041 100644
--- a/web/modules/linkit/src/Plugin/Field/FieldFormatter/LinkitFormatter.php
+++ b/web/modules/linkit/src/Plugin/Field/FieldFormatter/LinkitFormatter.php
@@ -2,12 +2,9 @@
 
 namespace Drupal\linkit\Plugin\Field\FieldFormatter;
 
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Path\PathValidatorInterface;
-use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\link\LinkItemInterface;
 use Drupal\link\Plugin\Field\FieldFormatter\LinkFormatter;
 use Drupal\linkit\Entity\Profile;
@@ -26,7 +23,7 @@
  *   }
  * )
  */
-class LinkitFormatter extends LinkFormatter implements ContainerFactoryPluginInterface {
+class LinkitFormatter extends LinkFormatter {
 
   /**
    * The substitution manager.
@@ -46,48 +43,10 @@ class LinkitFormatter extends LinkFormatter implements ContainerFactoryPluginInt
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $plugin_id,
-      $plugin_definition,
-      $configuration['field_definition'],
-      $configuration['settings'],
-      $configuration['label'],
-      $configuration['view_mode'],
-      $configuration['third_party_settings'],
-      $container->get('path.validator'),
-      $container->get('plugin.manager.linkit.substitution'),
-      $container->get('entity_type.manager')
-    );
-  }
-
-  /**
-   * Constructs a new LinkitFormatter.
-   *
-   * @param string $plugin_id
-   *   The plugin_id for the formatter.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
-   *   The definition of the field to which the formatter is associated.
-   * @param array $settings
-   *   The formatter settings.
-   * @param string $label
-   *   The formatter label display setting.
-   * @param string $view_mode
-   *   The view mode.
-   * @param array $third_party_settings
-   *   Third party settings.
-   * @param \Drupal\Core\Path\PathValidatorInterface $path_validator
-   *   The path validator service.
-   * @param \Drupal\linkit\SubstitutionManagerInterface $substitution_manager
-   *   The substitution manager.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, PathValidatorInterface $path_validator, SubstitutionManagerInterface $substitution_manager, EntityTypeManagerInterface $entity_type_manager) {
-    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings, $path_validator);
-    $this->substitutionManager = $substitution_manager;
-    $this->entityTypeManager = $entity_type_manager;
+    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    $instance->substitutionManager = $container->get('plugin.manager.linkit.substitution');
+    $instance->entityTypeManager = $container->get('entity_type.manager');
+    return $instance;
   }
 
   /**
@@ -152,6 +111,27 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
       $substituted_url = $this->getSubstitutedUrl($link_item);
       // Convert generated URL into a URL object.
       if ($substituted_url && ($url = \Drupal::pathValidator()->getUrlIfValid($substituted_url->getGeneratedUrl()))) {
+        // Keep query and fragment.
+        $parsed_url = parse_url($link_item->uri);
+        if (!empty($parsed_url['query'])) {
+          $parsed_query = [];
+          parse_str($parsed_url['query'], $parsed_query);
+          if (!empty($parsed_query)) {
+            $url->setOption('query', $parsed_query);
+          }
+        }
+        if (!empty($parsed_url['fragment'])) {
+          $url->setOption('fragment', $parsed_url['fragment']);
+        }
+        // Add cache dependency to the generated substituted URL.
+        $cacheable_metadata = BubbleableMetadata::createFromRenderArray($item)
+          ->addCacheableDependency($substituted_url);
+        // Add cache dependency to the referenced entity, e.g. for media direct
+        // file substitution.
+        if ($entity = LinkitHelper::getEntityFromUserInput($link_item->uri)) {
+          $cacheable_metadata->addCacheableDependency($entity);
+        }
+        $cacheable_metadata->applyTo($item);
         $item['#url'] = $url;
       }
     }
@@ -171,15 +151,13 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
    *   The substitution URL, or NULL if not able to retrieve it from the item.
    */
   protected function getSubstitutedUrl(LinkItemInterface $item) {
-    if (parse_url($item->uri, PHP_URL_SCHEME) == 'entity') {
-      if ($entity = LinkitHelper::getEntityFromUri($item->uri)) {
-        $profile = Profile::load($this->getSettings()['linkit_profile']);
-
-        /** @var \\Drupal\linkit\Plugin\Linkit\Matcher\EntityMatcher $matcher */
-        $matcher = $profile->getMatcherByEntityType($entity->getEntityTypeId());
-        $substitution_type = $matcher ? $matcher->getConfiguration()['settings']['substitution_type'] : SubstitutionManagerInterface::DEFAULT_SUBSTITUTION;
-        return $this->substitutionManager->createInstance($substitution_type)->getUrl($entity);
-      }
+    if ($entity = LinkitHelper::getEntityFromUserInput($item->uri)) {
+      $profile = Profile::load($this->getSettings()['linkit_profile']);
+
+      /** @var \\Drupal\linkit\Plugin\Linkit\Matcher\EntityMatcher $matcher */
+      $matcher = $profile->getMatcherByEntityType($entity->getEntityTypeId());
+      $substitution_type = $matcher ? $matcher->getConfiguration()['settings']['substitution_type'] : SubstitutionManagerInterface::DEFAULT_SUBSTITUTION;
+      return $this->substitutionManager->createInstance($substitution_type)->getUrl($entity);
     }
 
     return NULL;
diff --git a/web/modules/linkit/src/Plugin/Field/FieldWidget/LinkitWidget.php b/web/modules/linkit/src/Plugin/Field/FieldWidget/LinkitWidget.php
index d2f7823bfb14d1f967ff55df606a3eb42d451c6a..f67867e7e524c3701076ddbbec03741699e6c4e7 100644
--- a/web/modules/linkit/src/Plugin/Field/FieldWidget/LinkitWidget.php
+++ b/web/modules/linkit/src/Plugin/Field/FieldWidget/LinkitWidget.php
@@ -27,6 +27,7 @@ class LinkitWidget extends LinkWidget {
   public static function defaultSettings() {
     return [
       'linkit_profile' => 'default',
+      'linkit_auto_link_text' => FALSE,
     ] + parent::defaultSettings();
   }
 
@@ -37,11 +38,17 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     $item = $items[$delta];
     $uri = $item->uri;
     $uri_scheme = parse_url($uri, PHP_URL_SCHEME);
-    if (!empty($uri) && empty($uri_scheme)) {
+    $is_nolink = substr($uri, 0, 14) === 'route:<nolink>';
+    if (!empty($uri) && empty($uri_scheme) && $is_nolink) {
       $uri = LinkitHelper::uriFromUserInput($uri);
       $uri_scheme = parse_url($uri, PHP_URL_SCHEME);
     }
-    $uri_as_url = !empty($uri) ? Url::fromUri($uri)->toString() : '';
+    if ($is_nolink) {
+      $uri_as_url = $uri;
+    }
+    else {
+      $uri_as_url = !empty($uri) ? static::getUriAsDisplayableString($uri) : '';
+    }
     $linkit_profile_id = $this->getSetting('linkit_profile');
 
     // The current field value could have been entered by a different user.
@@ -95,11 +102,15 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       '#default_value' => isset($items[$delta]->title) ? $items[$delta]->title : NULL,
       '#maxlength' => 255,
       '#access' => $this->getFieldSetting('title') != DRUPAL_DISABLED,
+      '#required' => $this->getFieldSetting('title') === DRUPAL_REQUIRED && $element['#required'],
       '#attributes' => [
         'class' => ['linkit-widget-title'],
       ],
       '#error_no_message' => TRUE,
     ];
+    if ($this->getSetting('linkit_auto_link_text')) {
+      $element['title']['#attributes']['class'][] = 'linkit-widget-title--autofill-enabled';
+    }
     // Post-process the title field to make it conditionally required if URL is
     // non-empty. Omit the validation on the field edit form, since the field
     // settings cannot be saved otherwise.
@@ -144,6 +155,11 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       '#options' => $options,
       '#default_value' => $this->getSetting('linkit_profile'),
     ];
+    $elements['linkit_auto_link_text'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Automatically populate link text from entity label'),
+      '#default_value' => $this->getSetting('linkit_auto_link_text'),
+    ];
 
     return $elements;
   }
@@ -161,6 +177,12 @@ public function settingsSummary() {
       $summary[] = $this->t('Linkit profile: @linkit_profile', ['@linkit_profile' => $linkit_profile->label()]);
     }
 
+    $auto_link_text = $this->getSetting('linkit_auto_link_text') ? $this->t('Yes') : $this->t('No');
+    $summary[] = $this->t(
+      'Automatically populate link text from entity label: @auto_link_text',
+      ['@auto_link_text' => $auto_link_text]
+    );
+
     return $summary;
   }
 
@@ -175,4 +197,20 @@ public function massageFormValues(array $values, array $form, FormStateInterface
     return $values;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected static function getUriAsDisplayableString($uri) {
+    $scheme = parse_url($uri, PHP_URL_SCHEME);
+    if ($scheme === 'base') {
+      $uri_reference = explode(':', $uri, 2)[1];
+      $uri = 'internal:' . $uri_reference;
+    }
+    elseif ($scheme === 'entity') {
+      $uri_reference = explode(':', $uri, 2)[1];
+      $uri = '/' . $uri_reference;
+    }
+    return parent::getUriAsDisplayableString($uri);
+  }
+
 }
diff --git a/web/modules/linkit/src/Plugin/Linkit/Matcher/NolinkMatcher.php b/web/modules/linkit/src/Plugin/Linkit/Matcher/NolinkMatcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..90eee020b40ee45e700b38f54527c2d9f47f9acb
--- /dev/null
+++ b/web/modules/linkit/src/Plugin/Linkit/Matcher/NolinkMatcher.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Drupal\linkit\Plugin\Linkit\Matcher;
+
+use Drupal\linkit\MatcherBase;
+use Drupal\linkit\Suggestion\DescriptionSuggestion;
+use Drupal\linkit\Suggestion\SuggestionCollection;
+
+/**
+ * Provides a linkit matcher for route:<nolink>.
+ *
+ * @Matcher(
+ *   id = "nolink",
+ *   label = @Translation("Nolink"),
+ * )
+ */
+class NolinkMatcher extends MatcherBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute($string) {
+    $suggestions = new SuggestionCollection();
+
+    // Check for the text 'nolink' (e.g. like route:<nolink> with core link
+    // fields) and return route:<nolink> if it exists.
+    if (strpos($string, 'nolink') !== FALSE) {
+      $suggestion = new DescriptionSuggestion();
+      $suggestion->setLabel($this->t('Empty link'))
+        ->setPath('route:<nolink>')
+        ->setGroup($this->t('System'))
+        ->setDescription($this->t('An empty link'));
+
+      $suggestions->addSuggestion($suggestion);
+    }
+    return $suggestions;
+  }
+
+}
diff --git a/web/modules/linkit/src/Utility/LinkitHelper.php b/web/modules/linkit/src/Utility/LinkitHelper.php
index 56e9fab5bcb955600b9742127e78d5472f84e5c9..8376ca4048a3e2f1190eccfeae8a517b981537aa 100644
--- a/web/modules/linkit/src/Utility/LinkitHelper.php
+++ b/web/modules/linkit/src/Utility/LinkitHelper.php
@@ -4,6 +4,7 @@
 
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Url;
+use Drupal\Core\Entity\EntityInterface;
 
 /**
  * Provides helper to operate on URIs.
@@ -24,11 +25,23 @@ class LinkitHelper {
   public static function getEntityFromUri($uri) {
     // Stripe out potential query and fragment from the uri.
     $uri = strtok(strtok($uri, "?"), "#");
-    list($entity_type, $entity_id) = explode('/', substr($uri, 7), 2);
-    $entity_manager = \Drupal::entityTypeManager();
-    if ($entity_manager->getDefinition($entity_type, FALSE)) {
-      if ($entity = $entity_manager->getStorage($entity_type)->load($entity_id)) {
-        return \Drupal::service('entity.repository')->getTranslationFromContext($entity);
+    // Remove the schema, if any. Otherwise, remove the forwarding "/".
+    if (strpos($uri, 'entity:') !== FALSE) {
+      list(, $uri) = explode(':', $uri);
+    }
+    else {
+      $uri = trim($uri, '/');
+    }
+
+    if ($uri) {
+      $parts = explode('/', $uri, 2);
+      if (count($parts) == 2 && ($entity_type = $parts[0]) && ($entity_id = $parts[1])) {
+        $entity_manager = \Drupal::entityTypeManager();
+        if ($entity_manager->getDefinition($entity_type, FALSE)) {
+          if ($entity = $entity_manager->getStorage($entity_type)->load($entity_id)) {
+            return \Drupal::service('entity.repository')->getTranslationFromContext($entity);
+          }
+        }
       }
     }
 
@@ -58,7 +71,7 @@ public static function uriFromUserInput($input) {
       return $input;
     }
 
-    if (UrlHelper::isExternal($input)) {
+    if ($host && UrlHelper::isExternal($input)) {
       if (UrlHelper::externalIsLocal($input, \Drupal::request()->getSchemeAndHttpHost())) {
         // The link points to this domain. Make it relative to perform an entity
         // lookup.
@@ -73,11 +86,18 @@ public static function uriFromUserInput($input) {
 
     // Make sure the URI starts with a slash, otherwise the Url's factory
     // methods will throw exceptions.
+    $starts_with_hash = strpos($input, '#') === 0;
     $starts_with_a_slash = strpos($input, '/') === 0;
     $is_front = substr($input, 0, 7) === '<front>';
-    if (!$scheme && !$is_front && !$starts_with_a_slash) {
+    $is_nolink = substr($input, 0, 14) === 'route:<nolink>';
+    if (!$scheme && !$is_front && !$is_nolink && !$starts_with_a_slash && !$starts_with_hash) {
       $input = "/$input";
     }
+    // - '<front>' -> '/'
+    // - '<front>#foo' -> '/#foo'
+    if ($is_front) {
+      $input = '/' . substr($input, strlen('<front>'));
+    }
 
     $entity = self::getEntityFromUserInput($input);
     if ($entity) {
@@ -89,9 +109,15 @@ public static function uriFromUserInput($input) {
     $public_files_dir = \Drupal::service('stream_wrapper_manager')
       ->getViaScheme('public')
       ->getDirectoryPath();
-    if (strpos($input, "/$public_files_dir") === 0) {
+
+    $protocol_matches = [];
+    preg_match('/^([a-z]*?):/', $input, $protocol_matches);
+    if (!empty($public_files_dir) && strpos($input, "/$public_files_dir") === 0) {
       return "base:$input";
     }
+    elseif ((count($protocol_matches) > 1 && in_array($protocol_matches[1], UrlHelper::getAllowedProtocols())) || $is_nolink) {
+      return $input;
+    }
     else {
       return "internal:$input";
     }
@@ -110,7 +136,7 @@ public static function getEntityFromUserInput($input) {
     $scheme = parse_url($input, PHP_URL_SCHEME);
 
     // Check if it's an entity URI (e.g. entity:node/1).
-    if ($scheme === 'entity' && ($entity = static::getEntityFromUri($input))) {
+    if (($scheme === 'entity' || !$scheme) && ($entity = static::getEntityFromUri($input))) {
       return $entity;
     }
 
@@ -122,12 +148,16 @@ public static function getEntityFromUserInput($input) {
 
     try {
       $route_name = Url::fromUri($input)->getRouteName();
-      if ($route_name != "entity.node.edit_form" && $route_name != "node.add") {
-        $params = Url::fromUri($input)->getRouteParameters();
-        $possibly_an_entity_type = key($params);
+      $params = array_filter(Url::fromUri($input)->getRouteParameters());
+      $possibly_an_entity_type = key($params);
+      // Return only the entity, if this is a canonical route.
+      if ($route_name === 'entity.' . $possibly_an_entity_type . '.canonical') {
         $entity = \Drupal::entityTypeManager()
           ->getStorage($possibly_an_entity_type)
           ->load($params[$possibly_an_entity_type]);
+        if (!($entity instanceof EntityInterface)) {
+          return NULL;
+        }
         return \Drupal::service('entity.repository')
           ->getTranslationFromContext($entity);
       }
@@ -149,19 +179,20 @@ public static function getEntityFromUserInput($input) {
    *   The internal path if any matched. The input string otherwise.
    */
   public static function getPathByAlias($input) {
-    $prefixes = \Drupal::config('language.negotiation')->get('url.prefixes');
-    /** @var \Drupal\Core\Path\AliasManagerInterface $path_alias_manager */
-    $path_alias_manager = \Drupal::service('path.alias_manager');
+    $config = \Drupal::config('language.negotiation');
+    /** @var \Drupal\path_alias\AliasManagerInterface $path_alias_manager */
+    $path_alias_manager = \Drupal::service('path_alias.manager');
     /** @var \Drupal\Core\Language\LanguageManagerInterface $language_manager */
     $language_manager = \Drupal::service('language_manager');
 
     foreach ($language_manager->getLanguages() as $language) {
-      $prefix = $prefixes[$language->getId()];
-      // Strip the language prefix.
-      $initial_path = parse_url($input, PHP_URL_PATH);
-      $path_without_prefix = preg_replace("/^\/$prefix\//", '/', $initial_path);
-      $path_resolved = $path_alias_manager->getPathByAlias($path_without_prefix, $language->getId());
-      if ($path_resolved !== $path_without_prefix) {
+      $input_path = parse_url($input, PHP_URL_PATH);
+      if ($prefix = $config->get('url.prefixes.' . $language->getId())) {
+        // Strip the language prefix.
+        $input_path = preg_replace("/^\/$prefix\//", '/', $input_path);
+      }
+      $path_resolved = $path_alias_manager->getPathByAlias($input_path, $language->getId());
+      if ($path_resolved !== $input_path) {
         return $path_resolved . static::getQueryAndFragment($input);
       }
     }
diff --git a/web/modules/linkit/tests/src/FunctionalJavascript/LinkFieldTest.php b/web/modules/linkit/tests/src/FunctionalJavascript/LinkFieldTest.php
index de5343892e5a31a55598b54a50a4d97e394b4dce..b5a591072c886fe94055a6e26e368bd6630aa3bd 100644
--- a/web/modules/linkit/tests/src/FunctionalJavascript/LinkFieldTest.php
+++ b/web/modules/linkit/tests/src/FunctionalJavascript/LinkFieldTest.php
@@ -30,6 +30,11 @@ class LinkFieldTest extends WebDriverTestBase {
     'linkit',
   ];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'classy';
+
   /**
    * A linkit profile.
    *
@@ -43,6 +48,8 @@ class LinkFieldTest extends WebDriverTestBase {
   protected function setUp() {
     parent::setUp();
 
+    /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entityDisplayRepository */
+    $entityDisplayRepository = $this->container->get('entity_display.repository');
     $matcherManager = $this->container->get('plugin.manager.linkit.matcher');
     /** @var \Drupal\linkit\MatcherInterface $plugin */
 
@@ -72,12 +79,12 @@ protected function setUp() {
     ])->save();
 
     // Define our widget and formatter for this field.
-    entity_get_form_display('node', 'page', 'default')
+    $this->container->get('entity_display.repository')->getFormDisplay('node', 'page', 'default')
       ->setComponent('field_test_link', [
         'type' => 'linkit',
       ])
       ->save();
-    entity_get_display('node', 'page', 'default')
+    $entityDisplayRepository->getViewDisplay('node', 'page', 'default')
       ->setComponent('field_test_link', [
         'type' => 'linkit',
       ])
@@ -123,12 +130,14 @@ public function testLinkFieldWidgetAndFormatter() {
     $result_description = $assert_session->elementExists('css', 'li.linkit-result-line .linkit-result-line--description', $autocomplete_results_wrapper);
     $this->assertEquals('Linkit could not find any suggestions. This URL will be used as is.', $result_description->getText());
 
-    // Set the widget to use our profile and try again.
-    entity_get_form_display('node', 'page', 'default')
+    // Set the widget to use our profile and have autofill for link text
+    // enabled and try again.
+    $this->container->get('entity_display.repository')->getFormDisplay('node', 'page', 'default')
       ->setComponent('field_test_link', [
         'type' => 'linkit',
         'settings' => [
           'linkit_profile' => $this->linkitProfile->id(),
+          'linkit_auto_link_text' => TRUE,
         ],
       ])
       ->save();
@@ -235,6 +244,24 @@ public function testLinkFieldWidgetAndFormatter() {
     $href_value = $link_element->getAttribute('href');
     $this->assertContains('https://google.com#foobar', $href_value);
 
+    // Test that it is possible to add just the anchor.
+    $this->drupalGet('node/add/page');
+    $widget_wrapper = $assert_session->elementExists('css', '#edit-field-test-link-wrapper');
+    $uri_input = $assert_session->elementExists('css', 'input[name="field_test_link[0][uri]"]', $widget_wrapper);
+    $uri_input->setValue('#foobar');
+    $session->getDriver()->keyDown($uri_input->getXpath(), ' ');
+    $assert_session->waitOnAutocomplete();
+    $title_input = $assert_session->elementExists('css', 'input[name="field_test_link[0][title]"]', $widget_wrapper);
+    $title_input->setValue('Just a fragment');
+    $page->fillField('title[0][value]', 'Host test node 3.5');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('Host test node 3.5 has been created');
+
+    $field_wrapper = $assert_session->elementExists('css', '.field--type-link.field--name-field-test-link');
+    $link_element = $assert_session->elementExists('css', 'a', $field_wrapper);
+    $href_value = $link_element->getAttribute('href');
+    $this->assertEquals('#foobar', $href_value);
+
     // Test emails.
     $this->drupalGet('node/add/page');
 
@@ -329,6 +356,32 @@ public function testLinkFieldWidgetAndFormatter() {
     $this->assertEquals('Front page', $link_element->getText());
     $href_value = $link_element->getAttribute('href');
     $this->assertContains('/', $href_value);
+
+    // Test invalid input.
+    foreach (['foo:0123456', ':', '123:bar'] as $key => $invalid_string) {
+      $this->drupalGet('node/add/page');
+      $page->fillField('title[0][value]', 'Invalid string node ' . $key);
+      $widget_wrapper = $assert_session->elementExists('css', '#edit-field-test-link-wrapper');
+      $uri_input = $assert_session->elementExists('css', 'input[name="field_test_link[0][uri]"]', $widget_wrapper);
+      $uri_input->setValue($invalid_string);
+      $assert_session->assertWaitOnAjaxRequest();
+
+      $page->pressButton('Save');
+      $assert_session->pageTextContains("$invalid_string' is invalid.");
+    }
+
+    // Test valid ones.
+    foreach (['tel:0123456', 'irc:irc.freenode.net'] as $key => $invalid_string) {
+      $this->drupalGet('node/add/page');
+      $page->fillField('title[0][value]', 'Valid string node ' . $key);
+      $widget_wrapper = $assert_session->elementExists('css', '#edit-field-test-link-wrapper');
+      $uri_input = $assert_session->elementExists('css', 'input[name="field_test_link[0][uri]"]', $widget_wrapper);
+      $uri_input->setValue($invalid_string);
+      $assert_session->assertWaitOnAjaxRequest();
+
+      $page->pressButton('Save');
+      $assert_session->pageTextContains("page Valid string node $key has been created");
+    }
   }
 
 }
diff --git a/web/themes/asc_bootstrap/asc_bootstrap.theme b/web/themes/asc_bootstrap/asc_bootstrap.theme
index 8a8cf64e91c7eb7187df658729db81e5a0e5e819..8cadf8705be88c5297cfee81dacf8e52fd47c29f 100755
--- a/web/themes/asc_bootstrap/asc_bootstrap.theme
+++ b/web/themes/asc_bootstrap/asc_bootstrap.theme
@@ -32,13 +32,12 @@ function asc_bootstrap_preprocess_node(&$vars, $hook) {
  //get research landing page url alias
  $nids = \Drupal::entityQuery('node')->condition('type','research_landing_page')->execute();
  $lid = array_shift($nids);
- $vars['resrch_landing'] = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$lid);
+ $vars['resrch_landing'] = \Drupal::service('path_alias.manager')->getAliasByPath('/node/'.$lid);
 
  //get research gallery landing page url alias
  $nids2 = \Drupal::entityQuery('node')->condition('type','research_gallery_landing_page')->execute();
  $lid2 = array_shift($nids2);
- $vars['resrch_gall_landing'] = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$lid2);
-
+ $vars['resrch_gall_landing'] = \Drupal::service('path_alias.manager')->getAliasByPath('/node/'.$lid2);
 }
 
 /*