Reduce usages of Locutus

This commit is contained in:
Anton Liaposhchenko 2024-12-28 22:23:09 +02:00
parent e7aae35ef6
commit 8f8a6786fe
17 changed files with 50 additions and 105 deletions

@ -1,12 +1,10 @@
import type {TwingEscapingStrategyHandler} from "../escaping-strategy";
const phpSprintf = require('locutus/php/strings/sprintf');
export const createCssEscapingStrategyHandler = (): TwingEscapingStrategyHandler => {
return (value) => {
value = value.replace(/[^a-zA-Z0-9]/ug, (character: string) => {
const codePoint = character.codePointAt(0)!;
return phpSprintf('\\u%04X', codePoint);
return `\\u${codePoint.toString(16).padStart(4, '0').toUpperCase()}`
});
return value;

@ -1,7 +1,5 @@
import {TwingEscapingStrategyHandler} from "../escaping-strategy";
const phpOrd = require('locutus/php/strings/ord');
export const createHtmlAttributeEscapingStrategyHandler = (): TwingEscapingStrategyHandler => {
return (value) => {
value = value.replace(/[^a-zA-Z0-9,.\-_]/ug, function (matches: string) {
@ -25,7 +23,7 @@ export const createHtmlAttributeEscapingStrategyHandler = (): TwingEscapingStrat
]);
let chr = matches;
let ord = phpOrd(chr);
let ord = chr.charCodeAt(0);
/*
* The following replaces characters undefined in HTML with the

@ -1,7 +1,5 @@
import type {TwingEscapingStrategyHandler} from "../escaping-strategy";
const phpSprintf = require('locutus/php/strings/sprintf');
export const createJsEscapingStrategyHandler = (): TwingEscapingStrategyHandler => {
return (value) => {
// escape all non-alphanumeric characters
@ -25,13 +23,13 @@ export const createJsEscapingStrategyHandler = (): TwingEscapingStrategyHandler
]);
if (shortMap.has(char)) {
return shortMap.get(char);
return shortMap.get(char)!;
}
let codePoint = char.codePointAt(0)!;
if (codePoint <= 0x10000) {
return phpSprintf('\\u%04X', codePoint);
return `\\u${codePoint.toString(16).padStart(4, '0').toUpperCase()}`
}
// Split characters outside the BMP into surrogate pairs
@ -41,7 +39,7 @@ export const createJsEscapingStrategyHandler = (): TwingEscapingStrategyHandler
const high = 0xD800 | (codePoint >> 10);
const low = 0xDC00 | (codePoint & 0x3FF);
return phpSprintf('\\u%04X\\u%04X', high, low);
return `\\u${high.toString(16).padStart(4, '0').toUpperCase()}\\u${low.toString(16).padStart(4, '0').toUpperCase()}`
});
return value;

@ -1,7 +1,5 @@
import {TwingEscapingStrategyHandler} from "../escaping-strategy";
const phpRawurlencode = require('locutus/php/url/rawurlencode');
export const createUrlEscapingStrategyHandler = (): TwingEscapingStrategyHandler => {
return phpRawurlencode;
return (value) => encodeURIComponent(value);
};

@ -1,9 +1,12 @@
import type {TwingMarkup} from "../../../markup";
import {createMarkup} from "../../../markup";
import {TwingSynchronousCallable} from "../../../callable-wrapper";
import type { TwingMarkup } from "../../../markup";
import { createMarkup } from "../../../markup";
import { TwingSynchronousCallable } from "../../../callable-wrapper";
const phpNl2br = require('locutus/php/strings/nl2br');
export const nl2brSynchronously: TwingSynchronousCallable = (_executionContext, ...args: Array<any>): TwingMarkup => {
return createMarkup(phpNl2br(...args));
export const nl2brSynchronously: TwingSynchronousCallable = (
_executionContext,
value: string,
useXHTML: boolean = true
): TwingMarkup => {
const replaceWith = useXHTML ? "<br />" : "<br>";
return createMarkup(value.replace(/\r\n|\n\r|\r|\n/g, replaceWith));
};

@ -1,6 +1,5 @@
import {TwingSynchronousCallable} from "../../../callable-wrapper";
const phpNumberFormat = require('locutus/php/strings/number_format');
import phpNumberFormat from 'locutus/php/strings/number_format';
/**
* Number format filter.
@ -23,20 +22,11 @@ export const numberFormatSynchronously: TwingSynchronousCallable = (
decimalPoint: string | null,
thousandSeparator: string | null
): string => {
const {environment} = executionContext;
const {numberFormat} = environment;
const {numberFormat} = executionContext.environment;
if (numberOfDecimals === null) {
numberOfDecimals = numberFormat.numberOfDecimals;
}
if (decimalPoint === null) {
decimalPoint = numberFormat.decimalPoint;
}
if (thousandSeparator === null) {
thousandSeparator = numberFormat.thousandSeparator;
}
numberOfDecimals ??= numberFormat.numberOfDecimals;
decimalPoint ??= numberFormat.decimalPoint;
thousandSeparator ??= numberFormat.thousandSeparator;
return phpNumberFormat(number, numberOfDecimals, decimalPoint, thousandSeparator);
};

@ -1,9 +1,5 @@
import {TwingSynchronousCallable} from "../../../callable-wrapper";
const phpRound = require('locutus/php/math/round');
const phpCeil = require('locutus/php/math/ceil');
const phpFloor = require('locutus/php/math/floor');
/**
* Rounds a number.
*
@ -14,21 +10,14 @@ const phpFloor = require('locutus/php/math/floor');
* @returns {Promise<number>} The rounded number
*/
export const roundSynchronously: TwingSynchronousCallable = (_executionContext, value: any, precision: number, method: string): number => {
if (method === 'common') {
return phpRound(value, precision);
}
if (method !== 'ceil' && method !== 'floor') {
throw new Error('The round filter only supports the "common", "ceil", and "floor" methods.');
}
const intermediateValue = value * Math.pow(10, precision);
const intermediateDivider = Math.pow(10, precision);
const divider = Math.pow(10, precision);
if (method === 'ceil') {
return phpCeil(intermediateValue) / intermediateDivider;
}
else {
return phpFloor(intermediateValue) / intermediateDivider;
switch (method) {
case 'common': return Math.round(intermediateValue) / divider
case 'ceil': return Math.ceil(intermediateValue) / divider
case 'floor': return Math.floor(intermediateValue) / divider
default:
throw new Error('The round filter only supports the "common", "ceil", and "floor" methods.');
}
};

@ -2,8 +2,6 @@ import {isTraversable} from "../../../helpers/is-traversable";
import {iteratorToHash} from "../../../helpers/iterator-to-hash";
import {TwingSynchronousCallable} from "../../../callable-wrapper";
const phpHttpBuildQuery = require('locutus/php/url/http_build_query');
/**
* URL encodes (RFC 3986) a string as a path segment or a hash as a query string.
*
@ -17,9 +15,8 @@ export const urlEncodeSynchronously: TwingSynchronousCallable = (_executionConte
url = iteratorToHash(url);
}
const builtUrl: string = phpHttpBuildQuery(url, '', '&');
return builtUrl.replace(/\+/g, '%20');
const params = new URLSearchParams(url)
return params.toString()
}
return encodeURIComponent(url);

@ -1,5 +1,4 @@
import {iteratorToArray} from "../../../helpers/iterator-to-array";
import {max as phpMax} from "locutus/php/math";
import {TwingSynchronousCallable} from "../../../callable-wrapper";
export const maxSynchronously: TwingSynchronousCallable<[
@ -9,5 +8,5 @@ export const maxSynchronously: TwingSynchronousCallable<[
values = values[0];
}
return phpMax(iteratorToArray(values));
return Math.max(...iteratorToArray(values));
};

@ -1,5 +1,4 @@
import {iteratorToArray} from "../../../helpers/iterator-to-array";
import {min as phpMin} from "locutus/php/math";
import {TwingSynchronousCallable} from "../../../callable-wrapper";
export const minSynchronously: TwingSynchronousCallable<[
@ -9,5 +8,5 @@ export const minSynchronously: TwingSynchronousCallable<[
values = values[0];
}
return phpMin(iteratorToArray(values));
return Math.min(...iteratorToArray(values));
};

@ -32,19 +32,8 @@ export const randomSynchronously: TwingSynchronousCallable = (executionContext,
if (typeof values === 'number') {
let min: number;
if (max === null) {
if (values < 0) {
max = 0;
min = values;
}
else {
max = values;
min = 0;
}
}
else {
min = values;
}
min = Math.min(max ?? 0, values)
max = Math.max(max ?? 0, values)
return mt_rand(min, max);
}

@ -1,6 +1,6 @@
import {createSynchronousTemplate, TwingSynchronousTemplate} from "../../../template";
import {TwingSynchronousCallable} from "../../../callable-wrapper";
import * as createHash from "create-hash";
import createHash from "create-hash";
import {createSource} from "../../../source";
import {TwingSynchronousExecutionContext} from "../../../execution-context";

@ -3,7 +3,6 @@ import { examineObject } from "./examine-object";
import { isPlainObject } from "./is-plain-object";
import { get } from "./get";
import type { TwingAttributeAccessorCallType } from "../node/expression/attribute-accessor";
import { isBoolean, isFloat } from "./php";
import type {TwingSynchronousEnvironment} from "../environment";
const isObject = (value: unknown) =>
@ -48,10 +47,10 @@ export const getAttributeSynchronously = (
if (type !== "method") {
let arrayItem;
if (isBoolean(attribute)) {
if (typeof attribute === 'boolean') {
arrayItem = attribute ? 1 : 0;
} else if (isFloat(attribute)) {
arrayItem = parseInt(attribute);
} else if (typeof attribute === 'number') {
arrayItem = Math.floor(attribute);
} else {
arrayItem = attribute;
}

@ -2,17 +2,16 @@ import type {TwingBaseArrayNode} from "../node/expression/array";
import {TwingConstantNode} from "../node/expression/constant";
import {TwingBaseExpressionNode} from "../node/expression";
const array_chunk = require('locutus/php/array/array_chunk');
export const getKeyValuePairs = (
node: TwingBaseArrayNode<any>
): Array<{
key: TwingConstantNode,
value: TwingBaseExpressionNode
}> => {
const chunks: Array<[key: TwingConstantNode, value: TwingBaseExpressionNode]> = array_chunk(Object.values(node.children), 2);
return chunks.map(([key, value]) => {
return {key, value};
});
const values = Object.values(node)
const result = []
for (let i = 0; i < values.length; i += 2) {
result.push({ key: values[i], value: values[i + 1] })
}
return result
};

@ -2,14 +2,6 @@ import {isTraversable} from "./is-traversable";
import {iteratorToHash} from "./iterator-to-hash";
import {count} from "./count";
export const isBoolean = (candidate: any): boolean => {
return candidate === true || candidate === false;
};
export const isFloat = (candidate: any): boolean => {
return +candidate === candidate && (!isFinite(candidate) || !!(candidate % 1));
};
/**
* Adapted from https://github.com/kvz/locutus/blob/master/src/php/var/var_dump.js
*/

@ -13,7 +13,6 @@ import {getFunction} from "../../helpers/get-function";
import {getFilter} from "../../helpers/get-filter";
import type {TwingSynchronousTemplate} from "../../template";
const array_merge = require('locutus/php/array/array_merge');
const snakeCase = require('snake-case');
const normalizeName = (name: string) => {
@ -58,7 +57,7 @@ const getArguments = (
const callableParameters = acceptedArguments;
const names: Array<string> = [];
let optionalArguments: Array<string | TwingConstantNode> = [];
let optionalArguments: Array<TwingConstantNode> = [];
let arguments_: Array<TwingBaseNode> = [];
let position = 0;
@ -74,8 +73,7 @@ const getArguments = (
throw createRuntimeError(`Argument "${name}" is defined twice for ${callType} "${callName}".`, node, template.source);
}
arguments_ = array_merge(arguments_, optionalArguments);
arguments_.push(parameter.value);
arguments_ = [...arguments_, ...optionalArguments, parameter.value];
parameters.delete(name);
optionalArguments = [];
}
@ -83,8 +81,7 @@ const getArguments = (
const parameter = parameters.get(position);
if (parameter) {
arguments_ = array_merge(arguments_, optionalArguments);
arguments_.push(parameter.value);
arguments_ = [...arguments_, ...optionalArguments, parameter.value];
parameters.delete(position);
optionalArguments = [];
++position;
@ -113,8 +110,7 @@ const getArguments = (
}
if (arbitraryArguments.length) {
arguments_ = array_merge(arguments_, optionalArguments);
arguments_.push(...arbitraryArguments);
arguments_ = [...arguments_, ...optionalArguments, ...arbitraryArguments];
}
}

@ -7,6 +7,7 @@
"removeComments": false,
"strict": true,
"noUnusedParameters": true,
"noUnusedLocals": true
"noUnusedLocals": true,
"esModuleInterop": true
}
}