modernized less-vendor-prefixes and updated functions.php

This commit is contained in:
gtbu 2025-07-13 12:49:13 +02:00
parent c708ec8a4c
commit b72b8ffbf8
2 changed files with 344 additions and 46 deletions

View file

@ -0,0 +1,186 @@
// Universal Prefixes for LESS - 2025 Edition
//
// This file provides a manual alternative to Autoprefixer.
// It uses parts of https://github.com/JoelSutherland/LESS-Prefixer MIT license and of older Bootstrap 3.2 - vendor prefixes
// It has been updated to remove obsolete prefixes and focuses on those still relevant
// for modern browser support, primarily `-webkit-` for Safari and iOS.
// It's recommended to always include the standard, unprefixed property last. [7]
//
//---------------------------------------------------
// TABLE OF CONTENTS
//---------------------------------------------------
// .animation()
// .appearance()
// .backface-visibility()
// .box-shadow() - (No prefixes needed)
// .box-sizing() - (No prefixes needed)
// .columns()
// .filter()
// .flex-block() / .flex-inline() & Flexbox properties
// .hyphens()
// .keyframes()
// .linear-gradient()
// .placeholder()
// .transform() & related properties
// .transition() & related properties
// .user-select()
//---------------------------------------------------
// Animation
// `-webkit-` is still useful for full compatibility in some scenarios. [5]
.animation(@animation) {
-webkit-animation: @animation;
animation: @animation;
}
.animation-name(@name) {
-webkit-animation-name: @name;
animation-name: @name;
}
.animation-duration(@duration) {
-webkit-animation-duration: @duration;
animation-duration: @duration;
}
.animation-timing-function(@timing-function) {
-webkit-animation-timing-function: @timing-function;
animation-timing-function: @timing-function;
}
// Appearance
// Used to style form controls. `-webkit-` and `-moz-` are still required.
.appearance(@appearance) {
-webkit-appearance: @appearance;
-moz-appearance: @appearance;
appearance: @appearance;
}
// Backface Visibility
// Prevents flickering in 3D transforms. `-webkit-` is the primary prefix needed.
.backface-visibility(@visibility) {
-webkit-backface-visibility: @visibility;
backface-visibility: @visibility;
}
// Box Shadow
// Prefixes are no longer needed for modern browsers. [11]
.box-shadow(@shadow) {
box-shadow: @shadow;
}
// Box Sizing
// Fully supported in modern browsers without prefixes.
.box-sizing(@boxmodel) {
box-sizing: @boxmodel;
}
// CSS Columns
// `-webkit-` and `-moz-` can still be useful for full compatibility. [2]
.content-columns(@column-count; @column-gap: 20px) {
-webkit-column-count: @column-count;
-moz-column-count: @column-count;
column-count: @column-count;
-webkit-column-gap: @column-gap;
-moz-column-gap: @column-gap;
column-gap: @column-gap;
}
// Filter
// `-webkit-` is still necessary for some filter functions in Safari.
.filter(@filter) {
-webkit-filter: @filter;
filter: @filter;
}
// Flexbox
// The core properties are well-supported, but `-webkit-` can help with older Safari versions.
.flex-block() {
display: -webkit-flex;
display: flex;
}
.flex-inline() {
display: -webkit-inline-flex;
display: inline-flex;
}
.flex-direction(@direction: row) {
-webkit-flex-direction: @direction;
flex-direction: @direction;
}
.justify-content(@justify) {
-webkit-justify-content: @justify;
justify-content: @justify;
}
.align-items(@align) {
-webkit-align-items: @align;
align-items: @align;
}
.flex-grow(@grow: 1) {
-webkit-flex-grow: @grow;
flex-grow: @grow;
}
// Hyphens
// Useful for controlling text wrapping.
.hyphens(@mode: auto) {
-webkit-hyphens: @mode;
-moz-hyphens: @mode;
hyphens: @mode;
}
// Keyframes
// Requires `-webkit-` prefix for full compatibility.
.keyframes(@name; @args) {
@-webkit-keyframes @name { @args(); }
@keyframes @name { @args(); }
}
// Gradients
// Standard syntax is well-supported, but `-webkit-` can be a fallback.
.linear-gradient(@direction; @start-color; @end-color) {
background-color: @end-color; // Fallback
background-image: -webkit-linear-gradient(@direction, @start-color, @end-color);
background-image: linear-gradient(@direction, @start-color, @end-color);
}
// Placeholder Text
// The nested selector approach remains the standard way to style placeholders.
.placeholder(@color: #aaa) {
&::-webkit-input-placeholder { color: @color; }
&::-moz-placeholder { color: @color; opacity: 1; } // Firefox 19+
&:-ms-input-placeholder { color: @color; } // IE 10+
&::-ms-input-placeholder { color: @color; } // Edge
&::placeholder { color: @color; }
}
// Transformations
// `-webkit-` is the only prefix with some remaining relevance for transforms.
.transform(@transform) {
-webkit-transform: @transform;
transform: @transform;
}
.transform-origin(@origin) {
-webkit-transform-origin: @origin;
transform-origin: @origin;
}
// Transitions
// `-webkit-` is still useful for ensuring smooth transitions across all browsers.
.transition(@transition) {
-webkit-transition: @transition;
transition: @transition;
}
// User Select
// Prevents text selection. Prefixes are still necessary for full support.
.user-select(@select) {
-webkit-user-select: @select;
-moz-user-select: @select;
user-select: @select;
}

View file

@ -1,101 +1,213 @@
<?php
defined('is_running') or die('Not an entry point...');
/* Obsolete : https://www.php.net/manual/en/function.ctype-alnum.php */
if( !function_exists('ctype_alnum') ){
function ctype_alnum($string){
return (bool)preg_match('#^[a-z0-9]*$#i',$string);
}
}
}
/* Obsolete : https://www.php.net/manual/de/function.ctype-digit.php */
if( !function_exists('ctype_digit') ){
function ctype_digit($string){
return (bool)preg_match('#^[0-9]*$#',$string);
}
}
}
/**
* Also need:
* trim
* strspn
*
* obsolete now: https://www.php.net/manual/en/function.mb-strpos.php
* mb_strpos(
* string $haystack,
* string $needle,
* int $offset = 0,
* ?string $encoding = null
* ): int|false
*/
if( !function_exists('mb_strpos') ){
if( !function_exists('mb_strpos') ){
function mb_strpos(){
$args = func_get_args();
return call_user_func_array('strpos',$args);
}
function mb_strlen($str){
return strlen($str);
}
function mb_strtoupper($str){
return strtoupper($str);
}
function mb_strtolower($str){
return strtolower($str);
}
function mb_substr(){
$args = func_get_args();
return call_user_func_array('substr',$args);
}
function mb_substr_count($haystack,$needle){
return substr_count($haystack,$needle);
}
}
if( !function_exists('mb_substr_replace') ){
function mb_substr_replace($str,$repl,$start,$length=0){
$beg = mb_substr($str,0,$start);
$end = mb_substr($str,$start+$length);
return $beg.$repl.$end;
}
/**
* Multibyte-safe version of substr_replace() with array support.
* @param string|string[] $str Input string or array of strings.
* @param string|string[] $repl Replacement string or array of strings.
* @param int|int[] $start Start position or array of start positions.
* @param int|int[]|null $length (Optional) Length or array of lengths.
* @param string|null $encoding (Optional) Character encoding.
* @return string|string[]|false The modified string or array, or false on error.
*/
function mb_substr_replace(
string|array $str,
string|array $repl,
int|array $start,
int|array|null $length = null,
?string $encoding = null
): string|array|false {
$encoding ??= mb_internal_encoding();
if (is_array($str)) {
$num = count($str);
$repl = is_array($repl) ? array_slice($repl, 0, $num) : array_fill(0, $num, $repl);
$start = is_array($start) ? array_slice($start, 0, $num) : array_fill(0, $num, $start);
$length = is_array($length) ? array_slice($length, 0, $num) : array_fill(0, $num, $length ?? null);
return array_map(
fn($s, $r, $st, $l) => mb_substr_replace($s, $r, $st, $l, $encoding),
$str,
$repl,
$start,
$length
);
}
if (is_array($repl) || is_array($start) || is_array($length)) {
trigger_error('mb_substr_replace(): Passing an array for replacement, start, or length is not supported when the main string is not an array.', E_USER_WARNING);
return false;
}
$str_len = mb_strlen($str, $encoding);
if ($start < 0) {
$start = max(0, $str_len + $start);
} else {
$start = min($start, $str_len);
}
if ($length === null) {
$length = $str_len - $start;
} elseif ($length < 0) {
$length = max(0, $str_len - $start + $length);
} else {
$length = min($length, $str_len - $start);
}
$before = mb_substr($str, 0, $start, $encoding);
$after = mb_substr($str, $start + $length, null, $encoding);
return $before . $repl . $after;
}
if( !function_exists('mb_str_replace') ){
function mb_str_replace($search, $replace, $subject, &$count = 0){
/**
* Multibyte-safe str_replace() equivalent. *
* @param string|array $search
* @param string|array $replace
* @param string|array $subject
* @param int $count (by reference) Count of replacements made
* @param string|null $encoding Optional character encoding
* @return string|array
*/
if (!function_exists('mb_str_replace')) {
function mb_str_replace($search, $replace, $subject, &$count = 0, ?string $encoding = null) {
if (is_array($subject)) {
foreach ($subject as $key => $value) {
$subject[$key] = mb_str_replace($search, $replace, $value, $count, $encoding);
}
return $subject;
}
// Call mb_str_replace for each subject in array, recursively
if( is_array($subject) ){
foreach ($subject as $key => $value) {
$subject[$key] = mb_str_replace($search, $replace, $value, $count);
}
return $subject;
}
$encoding = $encoding ?? mb_internal_encoding();
$subject = (string) $subject;
$searches = is_array($search) ? array_values($search) : [$search];
$replacements = is_array($replace) ? array_values($replace) : [$replace];
$replacements = array_pad($replacements, count($searches), '');
// Normalize $search and $replace so they are both arrays of the same length
$searches = is_array($search) ? array_values($search) : array($search);
$replacements = is_array($replace) ? array_values($replace) : array($replace);
$replacements = array_pad($replacements, count($searches), '');
foreach( $searches as $key => $search ){
$parts = mb_split(preg_quote($search), $subject);
$count += count($parts) - 1;
$subject = implode($replacements[$key], $parts);
}
return $subject;
}
foreach ($searches as $key => $searchTerm) {
$searchTerm = (string) $searchTerm;
if ($searchTerm === '') {
trigger_error('mb_str_replace(): Empty search string is not supported', E_USER_WARNING);
continue;
}
$replaceWith = (string) $replacements[$key];
$offset = 0;
while (($pos = mb_strpos($subject, $searchTerm, $offset, $encoding)) !== false) {
$subject = mb_substr($subject, 0, $pos, $encoding)
. $replaceWith
. mb_substr($subject, $pos + mb_strlen($searchTerm, $encoding), null, $encoding);
$offset = $pos + mb_strlen($replaceWith, $encoding);
$count++;
}
}
return $subject;
}
}
if( !function_exists('mb_explode') ){
function mb_explode(){
$args = func_get_args();
$args[0] = preg_quote($args[0]);
return call_user_func_array('mb_split',$args);
}
if (!function_exists('mb_explode')) {
/**
* A multi-byte safe version of the native PHP explode() function,
* @param string $delimiter The boundary string.
* @param string $string The input string.
* @param int $limit
* @return array Returns an array of strings.
* @throws ValueError if the delimiter is an empty string, mimicking PHP 8's explode().
*/
function mb_explode(string $delimiter, string $string, int $limit = PHP_INT_MAX): array
{
if ($delimiter === '') {
throw new ValueError('mb_explode(): Argument #1 ($delimiter) must not be empty');
}
if (mb_strpos($string, $delimiter) === false) {
return [$string];
}
if ($limit === 0) {
$limit = 1;
}
$result = [];
$current_string = $string;
$delimiter_length = mb_strlen($delimiter);
if ($limit > 0) {
while (count($result) < $limit - 1) {
$pos = mb_strpos($current_string, $delimiter);
if ($pos === false) {
break;
}
$result[] = mb_substr($current_string, 0, $pos);
$current_string = mb_substr($current_string, $pos + $delimiter_length);
}
$result[] = $current_string;
return $result;
}
while (($pos = mb_strpos($current_string, $delimiter)) !== false) {
$result[] = mb_substr($current_string, 0, $pos);
$current_string = mb_substr($current_string, $pos + $delimiter_length);
}
$result[] = $current_string;
return array_slice($result, 0, $limit);
}
}
/* https://www.php.net/manual/de/function.gzopen.php */
if( !function_exists('gzopen') && function_exists('gzopen64') ){
function gzopen( $filename, $mode, $use_include_path = 0 ){
return gzopen64( $filename, $mode, $use_include_path );
}
}
/* If not, the function is defined as an empty function */
if( !function_exists('gpSettingsOverride') ){
function gpSettingsOverride(){}
}