feat(planning): grille hebdomadaire complète avec API et filtres
- Connexion API via proxy Angular (résolution CORS, base path /api) - Import CSS ng-zorro global pour les modales et composants - Filtres Camion/Show câblés sur l'affichage de la grille - Camions affichés via TrucksService (linkés au show du même créneau) - Panneau de détails : spectacles + camions du jour sélectionné - Modale de création de spectacle stylisée avec fond et centrage - Positionnement précis des events à la minute dans leur créneau - Auto-scroll vers l'heure courante au chargement - Ligne "maintenant" sur la colonne du jour actuel - Régénération des services OpenAPI (nouveaux noms de types) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+22
-129
@@ -6,15 +6,6 @@ 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}
|
||||
@@ -273,126 +264,31 @@ function removeDotSegments (path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* @param {import('../types/index').URIComponent} component
|
||||
* @param {boolean} esc
|
||||
* @returns {import('../types/index').URIComponent}
|
||||
*/
|
||||
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
|
||||
function normalizeComponentEncoding (component, esc) {
|
||||
const func = esc !== true ? escape : unescape
|
||||
if (component.scheme !== undefined) {
|
||||
component.scheme = func(component.scheme)
|
||||
}
|
||||
|
||||
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.userinfo !== undefined) {
|
||||
component.userinfo = func(component.userinfo)
|
||||
}
|
||||
|
||||
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.host !== undefined) {
|
||||
component.host = func(component.host)
|
||||
}
|
||||
|
||||
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.path !== undefined) {
|
||||
component.path = func(component.path)
|
||||
}
|
||||
|
||||
return output
|
||||
if (component.query !== undefined) {
|
||||
component.query = func(component.query)
|
||||
}
|
||||
if (component.fragment !== undefined) {
|
||||
component.fragment = func(component.fragment)
|
||||
}
|
||||
return component
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,7 +310,7 @@ function recomposeAuthority (component) {
|
||||
if (ipV6res.isIPV6 === true) {
|
||||
host = `[${ipV6res.escapedHost}]`
|
||||
} else {
|
||||
host = reescapeHostDelimiters(host, false)
|
||||
host = component.host
|
||||
}
|
||||
}
|
||||
uriTokens.push(host)
|
||||
@@ -431,10 +327,7 @@ function recomposeAuthority (component) {
|
||||
module.exports = {
|
||||
nonSimpleDomain,
|
||||
recomposeAuthority,
|
||||
reescapeHostDelimiters,
|
||||
normalizePercentEncoding,
|
||||
normalizePathEncoding,
|
||||
escapePreservingEscapes,
|
||||
normalizeComponentEncoding,
|
||||
removeDotSegments,
|
||||
isIPv4,
|
||||
isUUID,
|
||||
|
||||
Reference in New Issue
Block a user