avancement planning

This commit is contained in:
2026-05-26 11:58:39 +02:00
parent 619a2b240a
commit 150b97cd2e
4892 changed files with 99214 additions and 429382 deletions
+129 -22
View File
@@ -6,6 +6,15 @@ const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\d
/** @type {(value: string) => boolean} */
const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u)
/** @type {(value: string) => boolean} */
const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu)
/** @type {(value: string) => boolean} */
const isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu)
/** @type {(value: string) => boolean} */
const isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu)
/**
* @param {Array<string>} input
* @returns {string}
@@ -264,31 +273,126 @@ function removeDotSegments (path) {
}
/**
* @param {import('../types/index').URIComponent} component
* @param {boolean} esc
* @returns {import('../types/index').URIComponent}
* Re-escape RFC 3986 gen-delims that must not appear literally in the host.
* After the URI regex parses, these characters cannot be literal in the host
* field, so any that appear after decoding came from percent-encoding and
* must be restored to prevent authority structure changes.
*
* @param {string} host
* @param {boolean} isIP - true for IPv4/IPv6 hosts (skip colon re-escaping)
* @returns {string}
*/
function normalizeComponentEncoding (component, esc) {
const func = esc !== true ? escape : unescape
if (component.scheme !== undefined) {
component.scheme = func(component.scheme)
const HOST_DELIMS = { '@': '%40', '/': '%2F', '?': '%3F', '#': '%23', ':': '%3A' }
const HOST_DELIM_RE = /[@/?#:]/g
const HOST_DELIM_NO_COLON_RE = /[@/?#]/g
function reescapeHostDelimiters (host, isIP) {
const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE
re.lastIndex = 0
return host.replace(re, (ch) => HOST_DELIMS[ch])
}
/**
* Normalizes percent escapes and optionally decodes only unreserved ASCII bytes.
* Reserved delimiters such as `%2F` and `%2E` stay escaped.
*
* @param {string} input
* @param {boolean} [decodeUnreserved=false]
* @returns {string}
*/
function normalizePercentEncoding (input, decodeUnreserved = false) {
if (input.indexOf('%') === -1) {
return input
}
if (component.userinfo !== undefined) {
component.userinfo = func(component.userinfo)
let output = ''
for (let i = 0; i < input.length; i++) {
if (input[i] === '%' && i + 2 < input.length) {
const hex = input.slice(i + 1, i + 3)
if (isHexPair(hex)) {
const normalizedHex = hex.toUpperCase()
const decoded = String.fromCharCode(parseInt(normalizedHex, 16))
if (decodeUnreserved && isUnreserved(decoded)) {
output += decoded
} else {
output += '%' + normalizedHex
}
i += 2
continue
}
}
output += input[i]
}
if (component.host !== undefined) {
component.host = func(component.host)
return output
}
/**
* Normalizes path data without turning reserved escapes into live path syntax.
* Valid escapes are uppercased, raw unsafe characters are escaped, and only
* unreserved bytes that are not `.` are decoded.
*
* @param {string} input
* @returns {string}
*/
function normalizePathEncoding (input) {
let output = ''
for (let i = 0; i < input.length; i++) {
if (input[i] === '%' && i + 2 < input.length) {
const hex = input.slice(i + 1, i + 3)
if (isHexPair(hex)) {
const normalizedHex = hex.toUpperCase()
const decoded = String.fromCharCode(parseInt(normalizedHex, 16))
if (decoded !== '.' && isUnreserved(decoded)) {
output += decoded
} else {
output += '%' + normalizedHex
}
i += 2
continue
}
}
if (isPathCharacter(input[i])) {
output += input[i]
} else {
output += escape(input[i])
}
}
if (component.path !== undefined) {
component.path = func(component.path)
return output
}
/**
* Escapes a component while preserving existing valid percent escapes.
*
* @param {string} input
* @returns {string}
*/
function escapePreservingEscapes (input) {
let output = ''
for (let i = 0; i < input.length; i++) {
if (input[i] === '%' && i + 2 < input.length) {
const hex = input.slice(i + 1, i + 3)
if (isHexPair(hex)) {
output += '%' + hex.toUpperCase()
i += 2
continue
}
}
output += escape(input[i])
}
if (component.query !== undefined) {
component.query = func(component.query)
}
if (component.fragment !== undefined) {
component.fragment = func(component.fragment)
}
return component
return output
}
/**
@@ -310,7 +414,7 @@ function recomposeAuthority (component) {
if (ipV6res.isIPV6 === true) {
host = `[${ipV6res.escapedHost}]`
} else {
host = component.host
host = reescapeHostDelimiters(host, false)
}
}
uriTokens.push(host)
@@ -327,7 +431,10 @@ function recomposeAuthority (component) {
module.exports = {
nonSimpleDomain,
recomposeAuthority,
normalizeComponentEncoding,
reescapeHostDelimiters,
normalizePercentEncoding,
normalizePathEncoding,
escapePreservingEscapes,
removeDotSegments,
isIPv4,
isUUID,