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:
+157
-189
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @license Angular v20.3.21
|
||||
* @license Angular v20.3.11
|
||||
* (c) 2010-2025 Google LLC. https://angular.dev/
|
||||
* License: MIT
|
||||
*/
|
||||
@@ -449,7 +449,6 @@ var SecurityContext;
|
||||
SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT";
|
||||
SecurityContext[SecurityContext["URL"] = 4] = "URL";
|
||||
SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL";
|
||||
SecurityContext[SecurityContext["ATTRIBUTE_NO_BINDING"] = 6] = "ATTRIBUTE_NO_BINDING";
|
||||
})(SecurityContext || (SecurityContext = {}));
|
||||
var MissingTranslationStrategy;
|
||||
(function (MissingTranslationStrategy) {
|
||||
@@ -2976,10 +2975,6 @@ class Identifiers {
|
||||
// sanitization-related functions
|
||||
static sanitizeHtml = { name: 'ɵɵsanitizeHtml', moduleName: CORE };
|
||||
static sanitizeStyle = { name: 'ɵɵsanitizeStyle', moduleName: CORE };
|
||||
static validateAttribute = {
|
||||
name: 'ɵɵvalidateAttribute',
|
||||
moduleName: CORE,
|
||||
};
|
||||
static sanitizeResourceUrl = {
|
||||
name: 'ɵɵsanitizeResourceUrl',
|
||||
moduleName: CORE,
|
||||
@@ -2995,6 +2990,10 @@ class Identifiers {
|
||||
name: 'ɵɵtrustConstantResourceUrl',
|
||||
moduleName: CORE,
|
||||
};
|
||||
static validateIframeAttribute = {
|
||||
name: 'ɵɵvalidateIframeAttribute',
|
||||
moduleName: CORE,
|
||||
};
|
||||
// Decorators
|
||||
static inputDecorator = { name: 'Input', moduleName: CORE };
|
||||
static outputDecorator = { name: 'Output', moduleName: CORE };
|
||||
@@ -7807,11 +7806,13 @@ class ShadowCss {
|
||||
return cssText.replace(_cssColonHostRe, (_, hostSelectors, otherSelectors) => {
|
||||
if (hostSelectors) {
|
||||
const convertedSelectors = [];
|
||||
const hostSelectorArray = hostSelectors.split(',').map((p) => p.trim());
|
||||
for (const hostSelector of hostSelectorArray) {
|
||||
if (!hostSelector)
|
||||
for (const hostSelector of this._splitOnTopLevelCommas(hostSelectors)) {
|
||||
const trimmedHostSelector = hostSelector.trim();
|
||||
if (!trimmedHostSelector)
|
||||
break;
|
||||
const convertedSelector = _polyfillHostNoCombinator + hostSelector.replace(_polyfillHost, '') + otherSelectors;
|
||||
const convertedSelector = _polyfillHostNoCombinator +
|
||||
trimmedHostSelector.replace(_polyfillHost, '') +
|
||||
otherSelectors;
|
||||
convertedSelectors.push(convertedSelector);
|
||||
}
|
||||
return convertedSelectors.join(',');
|
||||
@@ -7821,6 +7822,38 @@ class ShadowCss {
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Generator function that splits a string on top-level commas (commas that are not inside parentheses).
|
||||
* Yields each part of the string between top-level commas. Terminates if an extra closing paren is found.
|
||||
*
|
||||
* @param text The string to split
|
||||
*/
|
||||
*_splitOnTopLevelCommas(text) {
|
||||
const length = text.length;
|
||||
let parens = 0;
|
||||
let prev = 0;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const charCode = text.charCodeAt(i);
|
||||
if (charCode === $LPAREN) {
|
||||
parens++;
|
||||
}
|
||||
else if (charCode === $RPAREN) {
|
||||
parens--;
|
||||
if (parens < 0) {
|
||||
// Found an extra closing paren. Assume we want the list terminated here
|
||||
yield text.slice(prev, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (charCode === $COMMA && parens === 0) {
|
||||
// Found a top-level comma, yield the current chunk
|
||||
yield text.slice(prev, i);
|
||||
prev = i + 1;
|
||||
}
|
||||
}
|
||||
// Yield the final chunk
|
||||
yield text.slice(prev);
|
||||
}
|
||||
/*
|
||||
* convert a rule like :host-context(.foo) > .bar { }
|
||||
*
|
||||
@@ -7837,34 +7870,14 @@ class ShadowCss {
|
||||
* .foo<scopeName> .bar { ... }
|
||||
*/
|
||||
_convertColonHostContext(cssText) {
|
||||
const length = cssText.length;
|
||||
let parens = 0;
|
||||
let prev = 0;
|
||||
let result = '';
|
||||
// Splits up the selectors on their top-level commas, processes the :host-context in them
|
||||
// individually and stitches them back together. This ensures that individual selectors don't
|
||||
// affect each other.
|
||||
for (let i = 0; i < length; i++) {
|
||||
const char = cssText[i];
|
||||
// If we hit a comma and there are no open parentheses, take the current chunk and process it.
|
||||
if (char === ',' && parens === 0) {
|
||||
result += this._convertColonHostContextInSelectorPart(cssText.slice(prev, i)) + ',';
|
||||
prev = i + 1;
|
||||
continue;
|
||||
}
|
||||
// We've hit the end. Take everything since the last comma.
|
||||
if (i === length - 1) {
|
||||
result += this._convertColonHostContextInSelectorPart(cssText.slice(prev));
|
||||
break;
|
||||
}
|
||||
if (char === '(') {
|
||||
parens++;
|
||||
}
|
||||
else if (char === ')') {
|
||||
parens--;
|
||||
}
|
||||
const results = [];
|
||||
for (const part of this._splitOnTopLevelCommas(cssText)) {
|
||||
results.push(this._convertColonHostContextInSelectorPart(part));
|
||||
}
|
||||
return result;
|
||||
return results.join(',');
|
||||
}
|
||||
_convertColonHostContextInSelectorPart(cssText) {
|
||||
return cssText.replace(_cssColonHostContextReGlobal, (selectorText, pseudoPrefix) => {
|
||||
@@ -7876,17 +7889,26 @@ class ShadowCss {
|
||||
const contextSelectorGroups = [[]];
|
||||
// There may be more than `:host-context` in this selector so `selectorText` could look like:
|
||||
// `:host-context(.one):host-context(.two)`.
|
||||
// Execute `_cssColonHostContextRe` over and over until we have extracted all the
|
||||
// `:host-context` selectors from this selector.
|
||||
let match;
|
||||
while ((match = _cssColonHostContextRe.exec(selectorText))) {
|
||||
// `match` = [':host-context(<selectors>)<rest>', <selectors>, <rest>]
|
||||
// The `<selectors>` could actually be a comma separated list: `:host-context(.one, .two)`.
|
||||
const newContextSelectors = (match[1] ?? '')
|
||||
.trim()
|
||||
.split(',')
|
||||
.map((m) => m.trim())
|
||||
.filter((m) => m !== '');
|
||||
// Loop until every :host-context in the compound selector has been processed.
|
||||
let startIndex = selectorText.indexOf(_polyfillHostContext);
|
||||
while (startIndex !== -1) {
|
||||
const afterPrefix = selectorText.substring(startIndex + _polyfillHostContext.length);
|
||||
if (!afterPrefix || afterPrefix[0] !== '(') {
|
||||
// Edge case of :host-context with no parens (e.g. `:host-context .inner`)
|
||||
selectorText = afterPrefix;
|
||||
startIndex = selectorText.indexOf(_polyfillHostContext);
|
||||
continue;
|
||||
}
|
||||
// Extract comma-separated selectors between the parentheses
|
||||
const newContextSelectors = [];
|
||||
let endIndex = 0; // Index of the closing paren of the :host-context()
|
||||
for (const selector of this._splitOnTopLevelCommas(afterPrefix.substring(1))) {
|
||||
endIndex = endIndex + selector.length + 1;
|
||||
const trimmed = selector.trim();
|
||||
if (trimmed) {
|
||||
newContextSelectors.push(trimmed);
|
||||
}
|
||||
}
|
||||
// We must duplicate the current selector group for each of these new selectors.
|
||||
// For example if the current groups are:
|
||||
// ```
|
||||
@@ -7913,7 +7935,8 @@ class ShadowCss {
|
||||
}
|
||||
}
|
||||
// Update the `selectorText` and see repeat to see if there are more `:host-context`s.
|
||||
selectorText = match[2];
|
||||
selectorText = afterPrefix.substring(endIndex + 1);
|
||||
startIndex = selectorText.indexOf(_polyfillHostContext);
|
||||
}
|
||||
// The context selectors now must be combined with each other to capture all the possible
|
||||
// selectors that `:host-context` can match. See `_combineHostContextSelectors()` for more
|
||||
@@ -8220,9 +8243,9 @@ class SafeSelector {
|
||||
});
|
||||
// Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
|
||||
// WS and "+" would otherwise be interpreted as selector separators.
|
||||
this._content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
|
||||
this._content = selector.replace(nthRegex, (_, pseudo, exp) => {
|
||||
const replaceBy = `__ph-${this.index}__`;
|
||||
this.placeholders.push(exp);
|
||||
this.placeholders.push(`(${exp})`);
|
||||
this.index++;
|
||||
return pseudo + replaceBy;
|
||||
});
|
||||
@@ -8254,13 +8277,19 @@ const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*([
|
||||
const _polyfillHost = '-shadowcsshost';
|
||||
// note: :host-context pre-processed to -shadowcsshostcontext.
|
||||
const _polyfillHostContext = '-shadowcsscontext';
|
||||
const _parenSuffix = '(?:\\((' + '(?:\\([^)(]*\\)|[^)(]*)+?' + ')\\))';
|
||||
// Matches text content with no parentheses, e.g., "foo"
|
||||
const _noParens = '[^)(]*';
|
||||
// Matches content with at most ONE level of nesting, e.g., "a(b)c"
|
||||
const _level1Parens = String.raw `(?:\(${_noParens}\)|${_noParens})+?`;
|
||||
// Matches content with at most TWO levels of nesting, e.g., "a(b(c)d)e"
|
||||
const _level2Parens = String.raw `(?:\(${_level1Parens}\)|${_noParens})+?`;
|
||||
const _parenSuffix = String.raw `(?:\((${_level2Parens})\))`;
|
||||
const nthRegex = new RegExp(String.raw `(:nth-[-\w]+)` + _parenSuffix, 'g');
|
||||
const _cssColonHostRe = new RegExp(_polyfillHost + _parenSuffix + '?([^,{]*)', 'gim');
|
||||
// note: :host-context patterns are terminated with `{`, as opposed to :host which
|
||||
// is both `{` and `,` because :host-context handles top-level commas differently.
|
||||
const _hostContextPattern = _polyfillHostContext + _parenSuffix + '?([^{]*)';
|
||||
const _cssColonHostContextReGlobal = new RegExp(`${_cssScopedPseudoFunctionPrefix}(${_hostContextPattern})`, 'gim');
|
||||
const _cssColonHostContextRe = new RegExp(_hostContextPattern, 'im');
|
||||
const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator';
|
||||
const _polyfillHostNoCombinatorOutsidePseudoFunction = new RegExp(`${_polyfillHostNoCombinator}(?![^(]*\\))`, 'g');
|
||||
const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s,]*)/;
|
||||
@@ -20333,6 +20362,7 @@ function interleave(left, right) {
|
||||
// =================================================================================================
|
||||
//
|
||||
// DO NOT EDIT THIS LIST OF SECURITY SENSITIVE PROPERTIES WITHOUT A SECURITY REVIEW!
|
||||
// Reach out to mprobst for details.
|
||||
//
|
||||
// =================================================================================================
|
||||
/** Map from tagName|propertyName to SecurityContext. Properties applying to all tags use '*'. */
|
||||
@@ -20350,7 +20380,6 @@ function SECURITY_SCHEMA() {
|
||||
'area|ping',
|
||||
'audio|src',
|
||||
'a|href',
|
||||
'a|xlink:href',
|
||||
'a|ping',
|
||||
'blockquote|cite',
|
||||
'body|background',
|
||||
@@ -20364,74 +20393,6 @@ function SECURITY_SCHEMA() {
|
||||
'track|src',
|
||||
'video|poster',
|
||||
'video|src',
|
||||
// MathML namespace
|
||||
// https://crsrc.org/c/third_party/blink/renderer/core/sanitizer/sanitizer.cc;l=753-768;drc=b3eb16372dcd3317d65e9e0265015e322494edcd;bpv=1;bpt=1
|
||||
'annotation|href',
|
||||
'annotation|xlink:href',
|
||||
'annotation-xml|href',
|
||||
'annotation-xml|xlink:href',
|
||||
'maction|href',
|
||||
'maction|xlink:href',
|
||||
'malignmark|href',
|
||||
'malignmark|xlink:href',
|
||||
'math|href',
|
||||
'math|xlink:href',
|
||||
'mroot|href',
|
||||
'mroot|xlink:href',
|
||||
'msqrt|href',
|
||||
'msqrt|xlink:href',
|
||||
'merror|href',
|
||||
'merror|xlink:href',
|
||||
'mfrac|href',
|
||||
'mfrac|xlink:href',
|
||||
'mglyph|href',
|
||||
'mglyph|xlink:href',
|
||||
'msub|href',
|
||||
'msub|xlink:href',
|
||||
'msup|href',
|
||||
'msup|xlink:href',
|
||||
'msubsup|href',
|
||||
'msubsup|xlink:href',
|
||||
'mmultiscripts|href',
|
||||
'mmultiscripts|xlink:href',
|
||||
'mprescripts|href',
|
||||
'mprescripts|xlink:href',
|
||||
'mi|href',
|
||||
'mi|xlink:href',
|
||||
'mn|href',
|
||||
'mn|xlink:href',
|
||||
'mo|href',
|
||||
'mo|xlink:href',
|
||||
'mpadded|href',
|
||||
'mpadded|xlink:href',
|
||||
'mphantom|href',
|
||||
'mphantom|xlink:href',
|
||||
'mrow|href',
|
||||
'mrow|xlink:href',
|
||||
'ms|href',
|
||||
'ms|xlink:href',
|
||||
'mspace|href',
|
||||
'mspace|xlink:href',
|
||||
'mstyle|href',
|
||||
'mstyle|xlink:href',
|
||||
'mtable|href',
|
||||
'mtable|xlink:href',
|
||||
'mtd|href',
|
||||
'mtd|xlink:href',
|
||||
'mtr|href',
|
||||
'mtr|xlink:href',
|
||||
'mtext|href',
|
||||
'mtext|xlink:href',
|
||||
'mover|href',
|
||||
'mover|xlink:href',
|
||||
'munder|href',
|
||||
'munder|xlink:href',
|
||||
'munderover|href',
|
||||
'munderover|xlink:href',
|
||||
'semantics|href',
|
||||
'semantics|xlink:href',
|
||||
'none|href',
|
||||
'none|xlink:href',
|
||||
]);
|
||||
registerContext(SecurityContext.RESOURCE_URL, [
|
||||
'applet|code',
|
||||
@@ -20447,33 +20408,6 @@ function SECURITY_SCHEMA() {
|
||||
'object|codebase',
|
||||
'object|data',
|
||||
'script|src',
|
||||
// The below two are for Script SVG
|
||||
// See: https://developer.mozilla.org/en-US/docs/Web/API/SVGScriptElement/href
|
||||
'script|href',
|
||||
'script|xlink:href',
|
||||
]);
|
||||
// Keep this in sync with SECURITY_SENSITIVE_ELEMENTS in packages/core/src/sanitization/sanitization.ts
|
||||
// Unknown is the internal tag name for unknown elements example used for host-bindings.
|
||||
// These are unsafe as `attributeName` can be `href` or `xlink:href`
|
||||
// See: http://b/463880509#comment7
|
||||
registerContext(SecurityContext.ATTRIBUTE_NO_BINDING, [
|
||||
'animate|attributeName',
|
||||
'set|attributeName',
|
||||
'animateMotion|attributeName',
|
||||
'animateTransform|attributeName',
|
||||
'unknown|attributeName',
|
||||
'iframe|sandbox',
|
||||
'iframe|allow',
|
||||
'iframe|allowFullscreen',
|
||||
'iframe|referrerPolicy',
|
||||
'iframe|csp',
|
||||
'iframe|fetchPriority',
|
||||
'unknown|sandbox',
|
||||
'unknown|allow',
|
||||
'unknown|allowFullscreen',
|
||||
'unknown|referrerPolicy',
|
||||
'unknown|csp',
|
||||
'unknown|fetchPriority',
|
||||
]);
|
||||
}
|
||||
return _SECURITY_SCHEMA;
|
||||
@@ -20482,6 +20416,32 @@ function registerContext(ctx, specs) {
|
||||
for (const spec of specs)
|
||||
_SECURITY_SCHEMA[spec.toLowerCase()] = ctx;
|
||||
}
|
||||
/**
|
||||
* The set of security-sensitive attributes of an `<iframe>` that *must* be
|
||||
* applied as a static attribute only. This ensures that all security-sensitive
|
||||
* attributes are taken into account while creating an instance of an `<iframe>`
|
||||
* at runtime.
|
||||
*
|
||||
* Note: avoid using this set directly, use the `isIframeSecuritySensitiveAttr` function
|
||||
* in the code instead.
|
||||
*/
|
||||
const IFRAME_SECURITY_SENSITIVE_ATTRS = new Set([
|
||||
'sandbox',
|
||||
'allow',
|
||||
'allowfullscreen',
|
||||
'referrerpolicy',
|
||||
'csp',
|
||||
'fetchpriority',
|
||||
]);
|
||||
/**
|
||||
* Checks whether a given attribute name might represent a security-sensitive
|
||||
* attribute of an <iframe>.
|
||||
*/
|
||||
function isIframeSecuritySensitiveAttr(attrName) {
|
||||
// The `setAttribute` DOM API is case-insensitive, so we lowercase the value
|
||||
// before checking it against a known security-sensitive attributes.
|
||||
return IFRAME_SECURITY_SENSITIVE_ATTRS.has(attrName.toLowerCase());
|
||||
}
|
||||
|
||||
class ElementSchemaRegistry {
|
||||
}
|
||||
@@ -21579,7 +21539,7 @@ function extractPlaceholderName(input) {
|
||||
* tags use '*'.
|
||||
*
|
||||
* Extracted from, and should be kept in sync with
|
||||
* https://www.w3.org/TR/trusted-types/#integrations
|
||||
* https://w3c.github.io/webappsec-trusted-types/dist/spec/#integrations
|
||||
*/
|
||||
const TRUSTED_TYPES_SINKS = new Set([
|
||||
// NOTE: All strings in this set *must* be lowercase!
|
||||
@@ -21590,7 +21550,6 @@ const TRUSTED_TYPES_SINKS = new Set([
|
||||
// NB: no TrustedScript here, as the corresponding tags are stripped by the compiler.
|
||||
// TrustedScriptURL
|
||||
'embed|src',
|
||||
'iframe|src',
|
||||
'object|codebase',
|
||||
'object|data',
|
||||
]);
|
||||
@@ -25265,7 +25224,6 @@ const sanitizerFns = new Map([
|
||||
[SecurityContext.SCRIPT, Identifiers.sanitizeScript],
|
||||
[SecurityContext.STYLE, Identifiers.sanitizeStyle],
|
||||
[SecurityContext.URL, Identifiers.sanitizeUrl],
|
||||
[SecurityContext.ATTRIBUTE_NO_BINDING, Identifiers.validateAttribute],
|
||||
]);
|
||||
/**
|
||||
* Map of security contexts to their trusted value function.
|
||||
@@ -25279,6 +25237,7 @@ const trustedValueFns = new Map([
|
||||
*/
|
||||
function resolveSanitizers(job) {
|
||||
for (const unit of job.units) {
|
||||
const elements = createOpXrefMap(unit);
|
||||
// For normal element bindings we create trusted values for security sensitive constant
|
||||
// attributes. However, for host bindings we skip this step (this matches what
|
||||
// TemplateDefinitionBuilder does).
|
||||
@@ -25299,8 +25258,8 @@ function resolveSanitizers(job) {
|
||||
let sanitizerFn = null;
|
||||
if (Array.isArray(op.securityContext) &&
|
||||
op.securityContext.length === 2 &&
|
||||
op.securityContext.includes(SecurityContext.URL) &&
|
||||
op.securityContext.includes(SecurityContext.RESOURCE_URL)) {
|
||||
op.securityContext.indexOf(SecurityContext.URL) > -1 &&
|
||||
op.securityContext.indexOf(SecurityContext.RESOURCE_URL) > -1) {
|
||||
// When the host element isn't known, some URL attributes (such as "src" and "href") may
|
||||
// be part of multiple different security contexts. In this case we use special
|
||||
// sanitization function and select the actual sanitizer at runtime based on a tag name
|
||||
@@ -25311,11 +25270,43 @@ function resolveSanitizers(job) {
|
||||
sanitizerFn = sanitizerFns.get(getOnlySecurityContext(op.securityContext)) ?? null;
|
||||
}
|
||||
op.sanitizer = sanitizerFn !== null ? importExpr(sanitizerFn) : null;
|
||||
// If there was no sanitization function found based on the security context of an
|
||||
// attribute/property, check whether this attribute/property is one of the
|
||||
// security-sensitive <iframe> attributes (and that the current element is actually an
|
||||
// <iframe>).
|
||||
if (op.sanitizer === null) {
|
||||
let isIframe = false;
|
||||
if (job.kind === CompilationJobKind.Host || op.kind === OpKind.DomProperty) {
|
||||
// Note: for host bindings defined on a directive, we do not try to find all
|
||||
// possible places where it can be matched, so we can not determine whether
|
||||
// the host element is an <iframe>. In this case, we just assume it is and append a
|
||||
// validation function, which is invoked at runtime and would have access to the
|
||||
// underlying DOM element to check if it's an <iframe> and if so - run extra checks.
|
||||
isIframe = true;
|
||||
}
|
||||
else {
|
||||
// For a normal binding we can just check if the element its on is an iframe.
|
||||
const ownerOp = elements.get(op.target);
|
||||
if (ownerOp === undefined || !isElementOrContainerOp(ownerOp)) {
|
||||
throw Error('Property should have an element-like owner');
|
||||
}
|
||||
isIframe = isIframeElement(ownerOp);
|
||||
}
|
||||
if (isIframe && isIframeSecuritySensitiveAttr(op.name)) {
|
||||
op.sanitizer = importExpr(Identifiers.validateIframeAttribute);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks whether the given op represents an iframe element.
|
||||
*/
|
||||
function isIframeElement(op) {
|
||||
return op.kind === OpKind.ElementStart && op.tag?.toLowerCase() === 'iframe';
|
||||
}
|
||||
/**
|
||||
* Asserts that there is only a single security context and returns it.
|
||||
*/
|
||||
@@ -29778,9 +29769,8 @@ class HtmlAstToIvyAst {
|
||||
// Note that validation is skipped and property mapping is disabled
|
||||
// due to the fact that we need to make sure a given prop is not an
|
||||
// input of a directive and directive matching happens at runtime.
|
||||
const isAttrOn = prop.name.toLowerCase().startsWith('attr.on');
|
||||
const bep = this.bindingParser.createBoundElementProperty(elementName, prop,
|
||||
/* skipValidation */ !isAttrOn,
|
||||
/* skipValidation */ true,
|
||||
/* mapPropertyName */ false);
|
||||
bound.push(BoundAttribute.fromBoundElementProperty(bep, i18n));
|
||||
}
|
||||
@@ -30676,30 +30666,8 @@ function verifyHostBindings(bindings, sourceSpan) {
|
||||
const bindingParser = makeBindingParser();
|
||||
bindingParser.createDirectiveHostEventAsts(bindings.listeners, sourceSpan);
|
||||
bindingParser.createBoundHostProperties(bindings.properties, sourceSpan);
|
||||
validateNoEventBindings(bindings, bindingParser, sourceSpan);
|
||||
return bindingParser.errors;
|
||||
}
|
||||
/**
|
||||
* Validates that there are no event attribute bindings in the host bindings.
|
||||
* @param bindings - Map of host bindings for the component.
|
||||
* @param bindingParser - Binding parser used to create the binding expression.
|
||||
* @param sourceSpan - Source span where the host bindings were defined.
|
||||
*/
|
||||
function validateNoEventBindings(bindings, bindingParser, sourceSpan) {
|
||||
for (const prop in bindings.properties) {
|
||||
const isAttr = prop.startsWith('attr.');
|
||||
const boundName = isAttr ? prop.slice(5) : prop;
|
||||
if (boundName.toLowerCase().startsWith('on')) {
|
||||
const errorType = isAttr ? 'attribute' : 'property';
|
||||
const suggestion = `(${boundName.slice(2)})=...`;
|
||||
let msg = `Binding to event ${errorType} '${boundName}' is disallowed for security reasons, please use ${suggestion}`;
|
||||
if (!isAttr) {
|
||||
msg += `\nIf '${prop}' is a directive input, make sure the directive is imported by the current module.`;
|
||||
}
|
||||
bindingParser.errors.push(new ParseError(sourceSpan, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
function compileStyles(styles, selector, hostSelector) {
|
||||
const shadowCss = new ShadowCss();
|
||||
return styles.map((style) => {
|
||||
@@ -32423,6 +32391,11 @@ function createR3ComponentDeferMetadata(boundTarget, deferBlockDependencies) {
|
||||
function extractHostBindings(propMetadata, sourceSpan, host) {
|
||||
// First parse the declarations from the metadata.
|
||||
const bindings = parseHostBindings(host || {});
|
||||
// After that check host bindings for errors
|
||||
const errors = verifyHostBindings(bindings, sourceSpan);
|
||||
if (errors.length) {
|
||||
throw new Error(errors.map((error) => error.msg).join('\n'));
|
||||
}
|
||||
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
|
||||
for (const field in propMetadata) {
|
||||
if (propMetadata.hasOwnProperty(field)) {
|
||||
@@ -32439,11 +32412,6 @@ function extractHostBindings(propMetadata, sourceSpan, host) {
|
||||
});
|
||||
}
|
||||
}
|
||||
// After that check host bindings for errors
|
||||
const errors = verifyHostBindings(bindings, sourceSpan);
|
||||
if (errors.length) {
|
||||
throw new Error(errors.map((error) => error.msg).join('\n'));
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
function isHostBinding(value) {
|
||||
@@ -34339,7 +34307,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
|
||||
function compileDeclareClassMetadata(metadata) {
|
||||
const definitionMap = new DefinitionMap();
|
||||
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
||||
definitionMap.set('type', metadata.type);
|
||||
definitionMap.set('decorators', metadata.decorators);
|
||||
@@ -34357,7 +34325,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
|
||||
callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
|
||||
callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
|
||||
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
||||
definitionMap.set('type', metadata.type);
|
||||
definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
|
||||
@@ -34452,7 +34420,7 @@ function createDirectiveDefinitionMap(meta) {
|
||||
const definitionMap = new DefinitionMap();
|
||||
const minVersion = getMinimumVersionForPartialOutput(meta);
|
||||
definitionMap.set('minVersion', literal(minVersion));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
// e.g. `type: MyDirective`
|
||||
definitionMap.set('type', meta.type.value);
|
||||
if (meta.isStandalone !== undefined) {
|
||||
@@ -34868,7 +34836,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
||||
function compileDeclareFactoryFunction(meta) {
|
||||
const definitionMap = new DefinitionMap();
|
||||
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
||||
definitionMap.set('type', meta.type.value);
|
||||
definitionMap.set('deps', compileDependencies(meta.deps));
|
||||
@@ -34903,7 +34871,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
||||
function createInjectableDefinitionMap(meta) {
|
||||
const definitionMap = new DefinitionMap();
|
||||
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
||||
definitionMap.set('type', meta.type.value);
|
||||
// Only generate providedIn property if it has a non-null value
|
||||
@@ -34954,7 +34922,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
||||
function createInjectorDefinitionMap(meta) {
|
||||
const definitionMap = new DefinitionMap();
|
||||
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
||||
definitionMap.set('type', meta.type.value);
|
||||
definitionMap.set('providers', meta.providers);
|
||||
@@ -34987,7 +34955,7 @@ function createNgModuleDefinitionMap(meta) {
|
||||
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
||||
}
|
||||
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
||||
definitionMap.set('type', meta.type.value);
|
||||
// We only generate the keys in the metadata if the arrays contain values.
|
||||
@@ -35038,7 +35006,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
||||
function createPipeDefinitionMap(meta) {
|
||||
const definitionMap = new DefinitionMap();
|
||||
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
||||
definitionMap.set('version', literal('20.3.21'));
|
||||
definitionMap.set('version', literal('20.3.11'));
|
||||
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
||||
// e.g. `type: MyPipe`
|
||||
definitionMap.set('type', meta.type.value);
|
||||
@@ -35194,7 +35162,7 @@ function compileHmrUpdateCallback(definitions, constantStatements, meta) {
|
||||
* @description
|
||||
* Entry point for all public APIs of the compiler package.
|
||||
*/
|
||||
const VERSION = new Version('20.3.21');
|
||||
const VERSION = new Version('20.3.11');
|
||||
|
||||
//////////////////////////////////////
|
||||
// THIS FILE HAS GLOBAL SIDE EFFECT //
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+3
-4
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @license Angular v20.3.21
|
||||
* @license Angular v20.3.11
|
||||
* (c) 2010-2025 Google LLC. https://angular.dev/
|
||||
* License: MIT
|
||||
*/
|
||||
@@ -51,8 +51,7 @@ declare enum SecurityContext {
|
||||
STYLE = 2,
|
||||
SCRIPT = 3,
|
||||
URL = 4,
|
||||
RESOURCE_URL = 5,
|
||||
ATTRIBUTE_NO_BINDING = 6
|
||||
RESOURCE_URL = 5
|
||||
}
|
||||
/**
|
||||
* Injection flags for DI.
|
||||
@@ -5311,13 +5310,13 @@ declare class Identifiers {
|
||||
static getInheritedFactory: ExternalReference;
|
||||
static sanitizeHtml: ExternalReference;
|
||||
static sanitizeStyle: ExternalReference;
|
||||
static validateAttribute: ExternalReference;
|
||||
static sanitizeResourceUrl: ExternalReference;
|
||||
static sanitizeScript: ExternalReference;
|
||||
static sanitizeUrl: ExternalReference;
|
||||
static sanitizeUrlOrResourceUrl: ExternalReference;
|
||||
static trustConstantHtml: ExternalReference;
|
||||
static trustConstantResourceUrl: ExternalReference;
|
||||
static validateIframeAttribute: ExternalReference;
|
||||
static inputDecorator: ExternalReference;
|
||||
static outputDecorator: ExternalReference;
|
||||
static viewChildDecorator: ExternalReference;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@angular/compiler",
|
||||
"version": "20.3.21",
|
||||
"version": "20.3.11",
|
||||
"description": "Angular - the compiler library",
|
||||
"author": "angular",
|
||||
"license": "MIT",
|
||||
|
||||
Reference in New Issue
Block a user