Skip to content

Commit

Permalink
Allow the exclusion of certain JS libraries from being bundled when i…
Browse files Browse the repository at this point in the history
…ntegrating Cypht with third-party software (cypht-org#1301)

* Allow the exclusion of certain JS libraries from being bundled when integrating Cypht with third-party software

* Fix unit tests and add the new variable to .env.example

* Bundle js files contents instead of the script tags
  • Loading branch information
mercihabam authored Oct 28, 2024
1 parent cf27b9d commit cc3eb91
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 83 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,6 @@ FANCY_LOGIN=false
#Windows CA certificates
#Get ON https://curl.se/ca/cacert.pem
#Depending on your PHP Directory, e.g. "c:\php\extras\ssl\cacert.pem"
WIN_CACERT_DIR=
WIN_CACERT_DIR=

JS_EXCLUDE_DEPS=
2 changes: 2 additions & 0 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -1317,4 +1317,6 @@
| Use this setting switch between the legacy login page and the fancy one
*/
'fancy_login' => env('FANCY_LOGIN', false),

'js_exclude_deps' => env('JS_EXCLUDE_DEPS', ''),
];
1 change: 1 addition & 0 deletions lib/framework.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
require APP_PATH.'lib/servers.php';
require APP_PATH.'lib/api.php';
require APP_PATH.'lib/webdav_formats.php';
require APP_PATH.'lib/js_libs.php';

require_once APP_PATH.'modules/core/functions.php';

Expand Down
32 changes: 32 additions & 0 deletions lib/js_libs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

define('JS_LIBS', [
'bootstrap' => 'vendor/twbs/bootstrap/dist/js/bootstrap.bundle.min.js',
'cash' => 'third_party/cash.min.js',
'resumable' => 'third_party/resumable.min.js',
'ays-beforeunload-shim' => 'third_party/ays-beforeunload-shim.js',
'jquery-are-you-sure' => 'third_party/jquery.are-you-sure.js',
'sortable' => 'third_party/sortable.min.js'
]);

function get_js_libs($exclude_deps = []) {
$js_lib = '';

foreach (JS_LIBS as $dep) {
if (!in_array($dep, $exclude_deps)) {
$js_lib .= '<script type="text/javascript" src="'.WEB_ROOT.$dep.'"></script>';
}
}
return $js_lib;
}

function get_js_libs_content($exclude_deps = []) {
$js_lib = '';

foreach (JS_LIBS as $dep) {
if (!in_array($dep, $exclude_deps)) {
$js_lib .= file_get_contents(APP_PATH.$dep);
}
}
return $js_lib;
}
3 changes: 2 additions & 1 deletion lib/modules_exec.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ public function merge_response($request, $session, $page) {
'router_login_state' => $session->is_active(),
'router_url_path' => $request->path,
'router_module_list' => $this->site_config->get_modules(),
'router_app_name' => $this->site_config->get('app_name', 'HM3')
'router_app_name' => $this->site_config->get('app_name', 'HM3'),
'router_js_exclude_deps' => $this->site_config->get('js_exclude_deps'),
));
}
}
Expand Down
62 changes: 62 additions & 0 deletions modules/core/js_modules/[cash]/extend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* extend cash.js with some useful bits */
$.inArray = function(item, list) {
for (var i in list) {
if (list[i] === item) {
return i;
}
}
return -1;
};
$.isEmptyObject = function(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
return false;
}
}
return true;
};
$.fn.submit = function() { this[0].submit(); }
$.fn.focus = function() { this[0].focus(); };
$.fn.serializeArray = function() {
var parts;
var res = [];
var args = this.serialize().split('&');
for (var i in args) {
parts = args[i].split('=');
if (parts[0] && parts[1]) {
res.push({'name': parts[0], 'value': parts[1]});
}
}
return res.map(function(x) {return {name: x.name, value: decodeURIComponent(x.value.replace(/\+/g, " "))}});
};
$.fn.sort = function(sort_function) {
var list = [];
for (var i=0, len=this.length; i < len; i++) {
list.push(this[i]);
}
return $(list.sort(sort_function));
};
$.fn.fadeOut = function(timeout = 600) {
return this.css("opacity", 0)
.css("transition", `opacity ${timeout}ms`)
};
$.fn.fadeOutAndRemove = function(timeout = 600) {
this.fadeOut(timeout)
var tm = setTimeout(() => {
this.remove();
clearTimeout(tm)
}, timeout);
return this;
};

$.fn.modal = function(action) {
const modalElement = this[0];
if (modalElement) {
const modal = new bootstrap.Modal(modalElement);
if (action === 'show') {
modal.show();
} else if (action === 'hide') {
modal.hide();
}
}
};
14 changes: 8 additions & 6 deletions modules/core/output_modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -541,12 +541,8 @@ class Hm_Output_page_js extends Hm_Output_Module {
protected function output() {
if (DEBUG_MODE) {
$res = '';
$js_lib = '<script type="text/javascript" src="'.WEB_ROOT.'vendor/twbs/bootstrap/dist/js/bootstrap.bundle.min.js"></script>';
$js_lib .= '<script type="text/javascript" src="'.WEB_ROOT.'third_party/cash.min.js"></script>';
$js_lib .= '<script type="text/javascript" src="'.WEB_ROOT.'third_party/resumable.min.js"></script>';
$js_lib .= '<script type="text/javascript" src="'.WEB_ROOT.'third_party/ays-beforeunload-shim.js"></script>';
$js_lib .= '<script type="text/javascript" src="'.WEB_ROOT.'third_party/jquery.are-you-sure.js"></script>';
$js_lib .= '<script type="text/javascript" src="'.WEB_ROOT.'third_party/sortable.min.js"></script>';
$js_exclude_dependencies = explode(',', $this->get('router_js_exclude_deps', ''));
$js_lib = get_js_libs($js_exclude_dependencies);
if ($this->get('encrypt_ajax_requests', '') || $this->get('encrypt_local_storage', '')) {
$js_lib .= '<script type="text/javascript" src="'.WEB_ROOT.'third_party/forge.min.js"></script>';
}
Expand All @@ -558,6 +554,12 @@ protected function output() {
if (in_array($mod, $mods, true)) {
$directoriesPattern = str_replace('/', DIRECTORY_SEPARATOR, "{*,*/*}");
foreach (glob($name.'js_modules' . DIRECTORY_SEPARATOR . $directoriesPattern . "*.js", GLOB_BRACE) as $js) {
if (preg_match('/\[(.+)\]/', $js, $matches)) {
$dep = $matches[1];
if (in_array($dep, $js_exclude_dependencies)) {
continue;
}
}
$res .= '<script type="text/javascript" src="'.WEB_ROOT.str_replace(APP_PATH, '', $js).'"></script>';
}

Expand Down
70 changes: 0 additions & 70 deletions modules/core/site.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,5 @@
'use strict';

/**
* NOTE: Tiki-Cypht integration dynamically removes everything from the begining of this file
* up to swipe_event function definition as it uses jquery (over cash.js) and has bootstrap
* framework already included. If you add code here that you wish to be included in Tiki-Cypht
* integration, add it below swipe_event function definition.
*/

/* extend cash.js with some useful bits */
$.inArray = function(item, list) {
for (var i in list) {
if (list[i] === item) {
return i;
}
}
return -1;
};
$.isEmptyObject = function(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
return false;
}
}
return true;
};
$.fn.submit = function() { this[0].submit(); }
$.fn.focus = function() { this[0].focus(); };
$.fn.serializeArray = function() {
var parts;
var res = [];
var args = this.serialize().split('&');
for (var i in args) {
parts = args[i].split('=');
if (parts[0] && parts[1]) {
res.push({'name': parts[0], 'value': parts[1]});
}
}
return res.map(function(x) {return {name: x.name, value: decodeURIComponent(x.value.replace(/\+/g, " "))}});
};
$.fn.sort = function(sort_function) {
var list = [];
for (var i=0, len=this.length; i < len; i++) {
list.push(this[i]);
}
return $(list.sort(sort_function));
};
$.fn.fadeOut = function(timeout = 600) {
return this.css("opacity", 0)
.css("transition", `opacity ${timeout}ms`)
};
$.fn.fadeOutAndRemove = function(timeout = 600) {
this.fadeOut(timeout)
var tm = setTimeout(() => {
this.remove();
clearTimeout(tm)
}, timeout);
return this;
};

$.fn.modal = function(action) {
const modalElement = this[0];
if (modalElement) {
const modal = new bootstrap.Modal(modalElement);
if (action === 'show') {
modal.show();
} else if (action === 'hide') {
modal.hide();
}
}
};

/* swipe event handler */
var swipe_event = function(el, callback, direction) {
var start_x, start_y, dist_x, dist_y, threshold = 150, restraint = 100,
Expand Down
13 changes: 8 additions & 5 deletions scripts/config_gen.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ function get_module_assignments($settings) {
$js = '';
$css = '';
$assets = array();
$js_exclude_dependencies = explode(',', ($settings['js_exclude_deps'] ?? ''));
$filters = array('allowed_output' => array(), 'allowed_get' => array(), 'allowed_cookie' => array(),
'allowed_post' => array(), 'allowed_server' => array(), 'allowed_pages' => array());

Expand All @@ -190,6 +191,12 @@ function get_module_assignments($settings) {
}
$directoriesPattern = str_replace('/', DIRECTORY_SEPARATOR, "{*,*/*}");
foreach (glob('modules' . DIRECTORY_SEPARATOR . $mod . DIRECTORY_SEPARATOR . 'js_modules' . DIRECTORY_SEPARATOR . $directoriesPattern . '*.js', GLOB_BRACE) as $js_module) {
if (preg_match('/\[(.+)\]/', $js_module, $matches)) {
$dep = $matches[1];
if (in_array($dep, $js_exclude_dependencies)) {
continue;
}
}
$js .= file_get_contents($js_module);
}
if (is_readable(sprintf("modules/%s/site.js", $mod))) {
Expand Down Expand Up @@ -255,7 +262,7 @@ function combine_includes($js, $js_compress, $css, $css_compress, $settings) {
}
if ($js) {
$mods = get_modules($settings);
$js_lib = file_get_contents(VENDOR_PATH . "twbs/bootstrap/dist/js/bootstrap.bundle.min.js");
$js_lib = get_js_libs_content(explode(',', $settings['js_exclude_deps']));
$js_lib .= file_get_contents("third_party/cash.min.js");
if (in_array('desktop_notifications', $mods, true)) {
$js_lib .= file_get_contents("third_party/push.min.js");
Expand All @@ -266,10 +273,6 @@ function combine_includes($js, $js_compress, $css, $css_compress, $settings) {
$settings['encrypt_local_storage'])) {
$js_lib .= file_get_contents("third_party/forge.min.js");
}
$js_lib .= file_get_contents("third_party/resumable.min.js");
$js_lib .= file_get_contents("third_party/ays-beforeunload-shim.js");
$js_lib .= file_get_contents("third_party/jquery.are-you-sure.js");
$js_lib .= file_get_contents("third_party/sortable.min.js");
file_put_contents('tmp.js', $js);
$js_out = $js_lib.compress($js, $js_compress, 'tmp.js');
$js_hash = build_integrity_hash($js_out);
Expand Down
2 changes: 2 additions & 0 deletions tests/phpunit/modules/core/output_modules_debug.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public function test_page_js_debug($given_router_module_list) {
$this->assertEquals(array($expected_output), $res->output_response);
}

// TODO: Add a test case excluding some js dependencies

static function router_module_list_provider() {
return [
'one module' => [['core']],
Expand Down

0 comments on commit cc3eb91

Please sign in to comment.