swup-1.0.0-alpha1/swup.module
swup.module
<?php
/**
* @file
* Drupal's integration with Swup.js library.
*
* Swup is a versatile and extensible page transition library for
* server-rendered websites. It makes your site feel like a single-page
* application with smooth transitions between pages.
*
* GitHub: https://github.com/swup/swup
* Website: https://swup.js.org/
* License: MIT licensed
*
* Copyright (C) 2016-2025 Georgy Marchuk
*/
use Drupal\Core\Asset\LibrariesDirectoryFileFinder;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Installer\InstallerKernel;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function swup_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.swup':
$site = 'https://swup.js.org/';
$gh = 'https://github.com/swup/swup';
$output = '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Swup integrates the Swup.js library to enable smooth page transitions in Drupal. It uses CDN builds by default, with optional local installation support.') . '</p>';
$output .= '<ul>';
$output .= '<li>' . t('Website: @url', ['@url' => $site]) . '</li>';
$output .= '<li>' . t('GitHub: @url', ['@url' => $gh]) . '</li>';
$output .= '</ul>';
$output .= '<h3>' . t('Features') . '</h3>';
$output .= '<ul>';
$output .= '<li>' . t('Smooth page transitions without full page reload.') . '</li>';
$output .= '<li>' . t('No jQuery dependency, pure vanilla JavaScript.') . '</li>';
$output .= '<li>' . t('Extensible plugin system for additional features.') . '</li>';
$output .= '<li>' . t('Cache management and preloading support.') . '</li>';
$output .= '</ul>';
$output .= '<h3>' . t('How it loads') . '</h3>';
$output .= '<p>' . t('Swup loads from CDN by default (unpkg or jsDelivr). For local installation, use Composer with Asset Packagist to install npm packages to libraries directory.') . '</p>';
$output .= '<h3>' . t('Basic usage') . '</h3>';
$output .= '<p>' . t('Add your transitions via theme or a custom module.') . '</p>';
$example = <<<'HTML'
<pre><code>const swup = new Swup({
containers: ['#main'],
animateHistoryBrowsing: true,
animationSelector: '[class*="transition-"]'
});</code></pre>
HTML;
$output .= $example;
$output .= '<p>' . t('For advanced control, enable the @ui module.', ['@ui' => 'Swup UI']) . '</p>';
return $output;
}
}
/**
* Finds the installation path of a specified library.
*
* This function searches for the library in these directories:
* - Current site: sites/site_name/libraries
* - Root: libraries
* - Installation profile: profiles/my_install_profile/libraries
* The first location found will be used.
*
* @param string $library_name
* The name of the library to find. Defaults to 'swup'.
*
* @return string|false
* The real path to the library file relative to the root directory. FALSE
* if not found.
*/
function swup_find_library($library_name = 'swup') {
// Get the current request.
$request = \Drupal::request();
// Determine the site path.
if (\Drupal::hasService('kernel')) {
$site_path = \Drupal::getContainer()->getParameter('site.path');
}
else {
// If there is no kernel available yet, call the static findSitePath().
$site_path = DrupalKernel::findSitePath($request);
}
// Get the application root.
$root = DRUPAL_ROOT;
// Get the profile extension list service.
$profile_extension_list = \Drupal::service('extension.list.profile');
// Get the current install profile.
$install_profile = \Drupal::installProfile();
// Create an instance of LibrariesDirectoryFileFinder.
$libraries_finder = new LibrariesDirectoryFileFinder($root, $site_path, $profile_extension_list, $install_profile);
// Find the library in the supported directories.
return $libraries_finder->find($library_name);
}
/**
* Check if the Swup library is available locally.
*
* This function checks for Swup installed via npm/Composer in the libraries
* directory. Since Swup doesn't ship with dist files in its GitHub repo,
* this expects the package to be installed from npm registry.
*
* @return bool
* TRUE if a local file is present; otherwise FALSE.
*/
function swup_check_installed() {
// Look for Swup in libraries directory.
$library_path = swup_find_library();
if ($library_path) {
// Check for the built file from npm package.
$swup_path = DRUPAL_ROOT . '/' . $library_path . '/dist/Swup.js';
if (file_exists($swup_path)) {
return TRUE;
}
// Also check for minified version.
$swup_min_path = DRUPAL_ROOT . '/' . $library_path . '/dist/Swup.min.js';
if (file_exists($swup_min_path)) {
return TRUE;
}
}
return FALSE;
}
/**
* Detect the version of installed Swup library.
*
* This function attempts to read the version from package.json file
* in the installed library directory.
*
* @return string|null
* The Swup version string if found, otherwise NULL.
*/
function swup_detect_version() {
// Look for Swup in libraries directory.
$library_path = swup_find_library();
if ($library_path) {
// Check for package.json file.
$package_json_path = DRUPAL_ROOT . '/' . $library_path . '/package.json';
if (file_exists($package_json_path)) {
$package_json = file_get_contents($package_json_path);
$package_data = json_decode($package_json, TRUE);
if (isset($package_data['version'])) {
return $package_data['version'];
}
}
}
return NULL;
}
/**
* Implements hook_page_attachments().
*/
function swup_page_attachments(array &$attachments) {
// Do not attach libraries during the installer.
if (InstallerKernel::installationAttempted()) {
return;
}
// If the UI submodule is disabled, attach automatically.
$module_handler = \Drupal::service('module_handler');
if (!$module_handler->moduleExists('swup_ui')) {
// Check if local installation exists.
if (swup_check_installed()) {
$attachments['#attached']['library'][] = 'swup/swup.local';
}
else {
// Use CDN versions with ESM and UMD fallback.
$attachments['#attached']['library'][] = 'swup/swup.cdn.esm';
$attachments['#attached']['library'][] = 'swup/swup.cdn.umd';
}
}
}
