valtech-components 2.0.288 → 2.0.289

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1007,15 +1007,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1007
1007
  /**
1008
1008
  * LinkProcessorService - Service for processing text content to convert URLs and internal routes into clickable links.
1009
1009
  *
1010
- * This service automatically detects external URLs (http/https) and internal routes (starting with /)
1011
- * and converts them into HTML anchor elements with appropriate attributes.
1010
+ * This service automatically detects external URLs (http/https), internal routes (starting with /),
1011
+ * and Markdown-style links [text](url) and converts them into HTML anchor elements with appropriate attributes.
1012
1012
  *
1013
1013
  * @example Basic usage:
1014
1014
  * ```typescript
1015
1015
  * constructor(private linkProcessor: LinkProcessorService) {}
1016
1016
  *
1017
1017
  * processText() {
1018
- * const text = 'Visit https://example.com or go to /profile';
1018
+ * const text = 'Visit https://example.com, go to /profile, or [check docs](https://docs.example.com)';
1019
1019
  * const processed = this.linkProcessor.processLinks(text);
1020
1020
  * // Returns SafeHtml with clickable links
1021
1021
  * }
@@ -1024,14 +1024,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1024
1024
  class LinkProcessorService {
1025
1025
  constructor(sanitizer) {
1026
1026
  this.sanitizer = sanitizer;
1027
- // Regex para detectar URLs completas (http/https)
1028
- this.urlRegex = /(https?:\/\/[^\s]+)/g;
1029
- // Regex para detectar rutas internas (empiezan con / pero no son URLs completas)
1030
- this.internalRouteRegex = /(\s|^)(\/[^\s]*)/g;
1027
+ // Regex para detectar URLs completas (http/https) - excluye caracteres de puntuación al final
1028
+ this.urlRegex = /(https?:\/\/[^\s,;.!?()]+)/g;
1029
+ // Regex para detectar rutas internas (empiezan con / pero no son URLs completas) - excluye puntuación
1030
+ this.internalRouteRegex = /(\s|^)(\/[^\s,;.!?()]*)/g;
1031
+ // Regex para detectar enlaces estilo Markdown [texto](url)
1032
+ this.markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
1031
1033
  }
1032
1034
  /**
1033
1035
  * Procesa texto para convertir enlaces en elementos <a> clickeables.
1034
- * Detecta automáticamente URLs externas e internas y las convierte en enlaces.
1036
+ * Detecta automáticamente URLs externas, rutas internas y enlaces estilo Markdown.
1035
1037
  *
1036
1038
  * @param text - Texto a procesar
1037
1039
  * @param config - Configuración del procesamiento
@@ -1040,10 +1042,11 @@ class LinkProcessorService {
1040
1042
  * @example
1041
1043
  * ```typescript
1042
1044
  * const result = this.linkProcessor.processLinks(
1043
- * 'Visit https://example.com or /profile',
1045
+ * 'Visit https://example.com, go to /profile, or [check docs](https://docs.example.com)',
1044
1046
  * {
1045
1047
  * openExternalInNewTab: true,
1046
1048
  * openInternalInNewTab: false,
1049
+ * processMarkdownLinks: true,
1047
1050
  * linkClass: 'custom-link'
1048
1051
  * }
1049
1052
  * );
@@ -1052,31 +1055,53 @@ class LinkProcessorService {
1052
1055
  processLinks(text, config = {}) {
1053
1056
  if (!text)
1054
1057
  return '';
1055
- const { openExternalInNewTab = true, openInternalInNewTab = false, linkClass = 'processed-link', externalLinkClass = 'external-link', internalLinkClass = 'internal-link', } = config;
1058
+ const { openExternalInNewTab = true, openInternalInNewTab = false, linkClass = 'processed-link', externalLinkClass = 'external-link', internalLinkClass = 'internal-link', processMarkdownLinks = true, } = config;
1056
1059
  let hasLinks = false;
1057
1060
  let processedText = text;
1058
- // Procesar URLs externas primero
1059
- if (this.urlRegex.test(text)) {
1061
+ // 1. Procesar enlaces estilo Markdown [texto](url) primero
1062
+ if (processMarkdownLinks && this.markdownLinkRegex.test(text)) {
1063
+ hasLinks = true;
1064
+ this.markdownLinkRegex.lastIndex = 0; // Reset regex
1065
+ processedText = processedText.replace(this.markdownLinkRegex, (match, linkText, url) => {
1066
+ const isExternal = /^https?:\/\//.test(url);
1067
+ const target = (isExternal ? openExternalInNewTab : openInternalInNewTab)
1068
+ ? isExternal
1069
+ ? ' target="_blank" rel="noopener noreferrer"'
1070
+ : ' target="_blank"'
1071
+ : '';
1072
+ const typeClass = isExternal ? externalLinkClass : internalLinkClass;
1073
+ const classes = `${linkClass} ${typeClass}`.trim();
1074
+ return `<a href="${url}"${target} class="${classes}">${linkText}</a>`;
1075
+ });
1076
+ }
1077
+ // 2. Procesar URLs externas directas
1078
+ if (this.urlRegex.test(processedText)) {
1060
1079
  hasLinks = true;
1061
1080
  this.urlRegex.lastIndex = 0; // Reset regex
1062
1081
  processedText = processedText.replace(this.urlRegex, url => {
1082
+ // Verificar que no esté ya dentro de un enlace procesado
1083
+ const beforeMatch = processedText.substring(0, processedText.indexOf(url));
1084
+ if (beforeMatch.includes('<a href="' + url + '"')) {
1085
+ return url; // Ya está procesado como Markdown link
1086
+ }
1063
1087
  const target = openExternalInNewTab ? ' target="_blank" rel="noopener noreferrer"' : '';
1064
1088
  const classes = `${linkClass} ${externalLinkClass}`.trim();
1065
1089
  return `<a href="${url}"${target} class="${classes}">${url}</a>`;
1066
1090
  });
1067
1091
  }
1068
- // Procesar rutas internas después
1092
+ // 3. Procesar rutas internas después
1069
1093
  if (this.internalRouteRegex.test(processedText)) {
1070
1094
  hasLinks = true;
1071
1095
  this.internalRouteRegex.lastIndex = 0; // Reset regex
1072
1096
  processedText = processedText.replace(this.internalRouteRegex, (match, prefix, route) => {
1073
1097
  // Solo procesar si no está ya dentro de un enlace
1074
- if (processedText.indexOf(`href="${route}"`) === -1) {
1075
- const target = openInternalInNewTab ? ' target="_blank"' : '';
1076
- const classes = `${linkClass} ${internalLinkClass}`.trim();
1077
- return `${prefix}<a href="${route}"${target} class="${classes}">${route}</a>`;
1098
+ const beforeMatch = processedText.substring(0, processedText.indexOf(match));
1099
+ if (beforeMatch.includes(`href="${route}"`)) {
1100
+ return match; // Ya está procesado
1078
1101
  }
1079
- return match;
1102
+ const target = openInternalInNewTab ? ' target="_blank"' : '';
1103
+ const classes = `${linkClass} ${internalLinkClass}`.trim();
1104
+ return `${prefix}<a href="${route}"${target} class="${classes}">${route}</a>`;
1080
1105
  });
1081
1106
  }
1082
1107
  // Si hay enlaces, sanitizar el HTML
@@ -1086,14 +1111,14 @@ class LinkProcessorService {
1086
1111
  return text;
1087
1112
  }
1088
1113
  /**
1089
- * Detecta si un texto contiene enlaces (URLs o rutas internas).
1114
+ * Detecta si un texto contiene enlaces (URLs, rutas internas o enlaces Markdown).
1090
1115
  *
1091
1116
  * @param text - Texto a analizar
1092
1117
  * @returns true si contiene enlaces
1093
1118
  *
1094
1119
  * @example
1095
1120
  * ```typescript
1096
- * const hasLinks = this.linkProcessor.hasLinks('Visit https://example.com');
1121
+ * const hasLinks = this.linkProcessor.hasLinks('Visit https://example.com or [docs](https://docs.com)');
1097
1122
  * // Returns: true
1098
1123
  * ```
1099
1124
  */
@@ -1103,20 +1128,24 @@ class LinkProcessorService {
1103
1128
  // Reset regex indices
1104
1129
  this.urlRegex.lastIndex = 0;
1105
1130
  this.internalRouteRegex.lastIndex = 0;
1106
- return this.urlRegex.test(text) || this.internalRouteRegex.test(text);
1131
+ this.markdownLinkRegex.lastIndex = 0;
1132
+ return (this.urlRegex.test(text) ||
1133
+ this.internalRouteRegex.test(text) ||
1134
+ this.markdownLinkRegex.test(text));
1107
1135
  }
1108
1136
  /**
1109
1137
  * Extrae todos los enlaces de un texto.
1110
1138
  *
1111
1139
  * @param text - Texto a analizar
1112
- * @returns Array de enlaces encontrados con su tipo
1140
+ * @returns Array de enlaces encontrados con su tipo y texto (si es Markdown)
1113
1141
  *
1114
1142
  * @example
1115
1143
  * ```typescript
1116
- * const links = this.linkProcessor.extractLinks('Visit https://example.com or /profile');
1144
+ * const links = this.linkProcessor.extractLinks('Visit https://example.com, /profile, or [docs](https://docs.com)');
1117
1145
  * // Returns: [
1118
- * // { url: 'https://example.com', type: 'external' },
1119
- * // { url: '/profile', type: 'internal' }
1146
+ * // { url: 'https://example.com', type: 'external', text: 'https://example.com' },
1147
+ * // { url: '/profile', type: 'internal', text: '/profile' },
1148
+ * // { url: 'https://docs.com', type: 'external', text: 'docs' }
1120
1149
  * // ]
1121
1150
  * ```
1122
1151
  */
@@ -1127,14 +1156,30 @@ class LinkProcessorService {
1127
1156
  // Reset regex indices
1128
1157
  this.urlRegex.lastIndex = 0;
1129
1158
  this.internalRouteRegex.lastIndex = 0;
1130
- // Extraer URLs externas
1159
+ this.markdownLinkRegex.lastIndex = 0;
1160
+ // Extraer enlaces Markdown primero
1131
1161
  let match;
1162
+ while ((match = this.markdownLinkRegex.exec(text)) !== null) {
1163
+ const url = match[2];
1164
+ const linkText = match[1];
1165
+ const type = /^https?:\/\//.test(url) ? 'external' : 'internal';
1166
+ links.push({ url, type, text: linkText });
1167
+ }
1168
+ // Extraer URLs externas directas
1132
1169
  while ((match = this.urlRegex.exec(text)) !== null) {
1133
- links.push({ url: match[1], type: 'external' });
1170
+ const url = match[1];
1171
+ // Verificar que no esté ya capturado como Markdown link
1172
+ if (!links.some(link => link.url === url)) {
1173
+ links.push({ url, type: 'external', text: url });
1174
+ }
1134
1175
  }
1135
- // Extraer rutas internas
1176
+ // Extraer rutas internas directas
1136
1177
  while ((match = this.internalRouteRegex.exec(text)) !== null) {
1137
- links.push({ url: match[2], type: 'internal' });
1178
+ const url = match[2];
1179
+ // Verificar que no esté ya capturado como Markdown link
1180
+ if (!links.some(link => link.url === url)) {
1181
+ links.push({ url, type: 'internal', text: url });
1182
+ }
1138
1183
  }
1139
1184
  return links;
1140
1185
  }
@@ -2053,7 +2098,7 @@ class TextComponent {
2053
2098
  <p [class]="props.size" [class.bold]="props.bold">{{ displayContent$ | async }}</p>
2054
2099
  }
2055
2100
  </ion-text>
2056
- `, isInline: true, styles: ["@charset \"UTF-8\";:root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143,73,248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255,255,255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.75rem;line-height:1.25rem;font-weight:400}.small.bold{font-size:.75rem;line-height:1.25rem;font-weight:700}.medium{font-size:.875rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.medium{font-size:1rem;line-height:1.5rem}}.medium.bold{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium.bold{font-size:1rem;line-height:1.5rem}}.large{font-size:1rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.large{font-size:1.125rem;line-height:1.5rem}}.large.bold{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large.bold{font-size:1.125rem;line-height:1.5rem}}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.bold{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge.bold{font-size:1.5rem;line-height:2rem}}:host ::ng-deep .processed-link{color:var(--ion-color-primary, #3880ff);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;transition:color .3s ease}:host ::ng-deep .processed-link:hover{color:var(--ion-color-primary-shade, #3171e0);text-decoration-thickness:2px}:host ::ng-deep .processed-link:active{color:var(--ion-color-primary-tint, #4c8dff)}:host ::ng-deep .external-link:after{content:\" \\2197\";font-size:.8em;opacity:.7}:host ::ng-deep .internal-link{color:var(--ion-color-secondary, #0cd1e8)}:host ::ng-deep .internal-link:hover{color:var(--ion-color-secondary-shade, #0bb8cc)}\n"], dependencies: [{ kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: ProcessLinksPipe, name: "processLinks" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2101
+ `, isInline: true, styles: ["@charset \"UTF-8\";:root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143,73,248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255,255,255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.75rem;line-height:1.25rem;font-weight:400}.small.bold{font-size:.75rem;line-height:1.25rem;font-weight:700}.medium{font-size:.875rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.medium{font-size:1rem;line-height:1.5rem}}.medium.bold{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium.bold{font-size:1rem;line-height:1.5rem}}.large{font-size:1rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.large{font-size:1.125rem;line-height:1.5rem}}.large.bold{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large.bold{font-size:1.125rem;line-height:1.5rem}}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.bold{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge.bold{font-size:1.5rem;line-height:2rem}}:host ::ng-deep .processed-link{color:var(--ion-color-primary, #3880ff);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;transition:color .3s ease}:host ::ng-deep .processed-link:hover{color:var(--ion-color-primary-shade, #3171e0);text-decoration-thickness:2px}:host ::ng-deep .processed-link:active{color:var(--ion-color-primary-tint, #4c8dff)}:host ::ng-deep .external-link:after{content:\" \\2197\";font-size:.8em;opacity:.7}:host ::ng-deep .internal-link{color:var(--ion-color-primary, #0cd1e8)}:host ::ng-deep .internal-link:hover{color:var(--ion-color-primary-shade, #0bb8cc)}\n"], dependencies: [{ kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: ProcessLinksPipe, name: "processLinks" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2057
2102
  }
2058
2103
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextComponent, decorators: [{
2059
2104
  type: Component,
@@ -2069,7 +2114,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2069
2114
  <p [class]="props.size" [class.bold]="props.bold">{{ displayContent$ | async }}</p>
2070
2115
  }
2071
2116
  </ion-text>
2072
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@charset \"UTF-8\";:root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143,73,248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255,255,255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.75rem;line-height:1.25rem;font-weight:400}.small.bold{font-size:.75rem;line-height:1.25rem;font-weight:700}.medium{font-size:.875rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.medium{font-size:1rem;line-height:1.5rem}}.medium.bold{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium.bold{font-size:1rem;line-height:1.5rem}}.large{font-size:1rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.large{font-size:1.125rem;line-height:1.5rem}}.large.bold{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large.bold{font-size:1.125rem;line-height:1.5rem}}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.bold{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge.bold{font-size:1.5rem;line-height:2rem}}:host ::ng-deep .processed-link{color:var(--ion-color-primary, #3880ff);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;transition:color .3s ease}:host ::ng-deep .processed-link:hover{color:var(--ion-color-primary-shade, #3171e0);text-decoration-thickness:2px}:host ::ng-deep .processed-link:active{color:var(--ion-color-primary-tint, #4c8dff)}:host ::ng-deep .external-link:after{content:\" \\2197\";font-size:.8em;opacity:.7}:host ::ng-deep .internal-link{color:var(--ion-color-secondary, #0cd1e8)}:host ::ng-deep .internal-link:hover{color:var(--ion-color-secondary-shade, #0bb8cc)}\n"] }]
2117
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@charset \"UTF-8\";:root{--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8}@media (prefers-color-scheme: dark){:root{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143,73,248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255,255,255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}.small{font-size:.75rem;line-height:1.25rem;font-weight:400}.small.bold{font-size:.75rem;line-height:1.25rem;font-weight:700}.medium{font-size:.875rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.medium{font-size:1rem;line-height:1.5rem}}.medium.bold{font-size:.875rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.medium.bold{font-size:1rem;line-height:1.5rem}}.large{font-size:1rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.large{font-size:1.125rem;line-height:1.5rem}}.large.bold{font-size:1rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.large.bold{font-size:1.125rem;line-height:1.5rem}}.xlarge{font-size:1.125rem;line-height:1.5rem;font-weight:400}@media (min-width: 768px){.xlarge{font-size:1.5rem;line-height:2rem}}.xlarge.bold{font-size:1.125rem;line-height:1.5rem;font-weight:700}@media (min-width: 768px){.xlarge.bold{font-size:1.5rem;line-height:2rem}}:host ::ng-deep .processed-link{color:var(--ion-color-primary, #3880ff);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;transition:color .3s ease}:host ::ng-deep .processed-link:hover{color:var(--ion-color-primary-shade, #3171e0);text-decoration-thickness:2px}:host ::ng-deep .processed-link:active{color:var(--ion-color-primary-tint, #4c8dff)}:host ::ng-deep .external-link:after{content:\" \\2197\";font-size:.8em;opacity:.7}:host ::ng-deep .internal-link{color:var(--ion-color-primary, #0cd1e8)}:host ::ng-deep .internal-link:hover{color:var(--ion-color-primary-shade, #0bb8cc)}\n"] }]
2073
2118
  }], ctorParameters: () => [{ type: ContentService }, { type: LinkProcessorService }], propDecorators: { props: [{
2074
2119
  type: Input
2075
2120
  }] } });
@@ -6572,6 +6617,36 @@ class LinkProcessingExampleComponent {
6572
6617
  internalLinkClass: 'internal-same-tab',
6573
6618
  },
6574
6619
  };
6620
+ this.markdownLinksProps = {
6621
+ content: 'Consulta [la documentación de Angular](https://angular.io/docs) y ve a [configuración del perfil](/profile/settings) para más opciones.',
6622
+ size: 'medium',
6623
+ color: 'dark',
6624
+ bold: false,
6625
+ processLinks: true,
6626
+ linkConfig: {
6627
+ openExternalInNewTab: true,
6628
+ openInternalInNewTab: false,
6629
+ processMarkdownLinks: true,
6630
+ linkClass: 'markdown-link',
6631
+ externalLinkClass: 'markdown-external',
6632
+ internalLinkClass: 'markdown-internal',
6633
+ },
6634
+ };
6635
+ this.mixedFormatsProps = {
6636
+ content: 'Aquí hay [documentación oficial](https://angular.io/docs), un enlace directo https://github.com/angular/angular, y una ruta interna /dashboard/analytics. ¡Todos funcionan!',
6637
+ size: 'medium',
6638
+ color: 'dark',
6639
+ bold: false,
6640
+ processLinks: true,
6641
+ linkConfig: {
6642
+ openExternalInNewTab: true,
6643
+ openInternalInNewTab: false,
6644
+ processMarkdownLinks: true,
6645
+ linkClass: 'mixed-link',
6646
+ externalLinkClass: 'mixed-external',
6647
+ internalLinkClass: 'mixed-internal',
6648
+ },
6649
+ };
6575
6650
  }
6576
6651
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkProcessingExampleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6577
6652
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: LinkProcessingExampleComponent, isStandalone: true, selector: "val-link-processing-example", ngImport: i0, template: `
@@ -6602,6 +6677,16 @@ class LinkProcessingExampleComponent {
6602
6677
  <h3>Enlaces sin abrir en nueva pestaña:</h3>
6603
6678
  <val-text [props]="sameTabLinksProps"></val-text>
6604
6679
  </div>
6680
+
6681
+ <div class="example-section">
6682
+ <h3>Enlaces estilo Markdown [texto](url):</h3>
6683
+ <val-text [props]="markdownLinksProps"></val-text>
6684
+ </div>
6685
+
6686
+ <div class="example-section">
6687
+ <h3>Mezcla de enlaces directos y Markdown:</h3>
6688
+ <val-text [props]="mixedFormatsProps"></val-text>
6689
+ </div>
6605
6690
  </div>
6606
6691
  `, isInline: true, styles: [".link-examples{padding:20px;max-width:800px}.example-section{margin-bottom:24px;padding:16px;border:1px solid var(--ion-color-light, #f4f5f8);border-radius:8px;background:var(--ion-color-light-tint, #f5f6f9)}h2{color:var(--ion-color-primary, #3880ff);margin-bottom:20px}h3{color:var(--ion-color-dark, #222428);margin-bottom:10px;font-size:16px}\n"], dependencies: [{ kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }] }); }
6607
6692
  }
@@ -6635,6 +6720,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
6635
6720
  <h3>Enlaces sin abrir en nueva pestaña:</h3>
6636
6721
  <val-text [props]="sameTabLinksProps"></val-text>
6637
6722
  </div>
6723
+
6724
+ <div class="example-section">
6725
+ <h3>Enlaces estilo Markdown [texto](url):</h3>
6726
+ <val-text [props]="markdownLinksProps"></val-text>
6727
+ </div>
6728
+
6729
+ <div class="example-section">
6730
+ <h3>Mezcla de enlaces directos y Markdown:</h3>
6731
+ <val-text [props]="mixedFormatsProps"></val-text>
6732
+ </div>
6638
6733
  </div>
6639
6734
  `, styles: [".link-examples{padding:20px;max-width:800px}.example-section{margin-bottom:24px;padding:16px;border:1px solid var(--ion-color-light, #f4f5f8);border-radius:8px;background:var(--ion-color-light-tint, #f5f6f9)}h2{color:var(--ion-color-primary, #3880ff);margin-bottom:20px}h3{color:var(--ion-color-dark, #222428);margin-bottom:10px;font-size:16px}\n"] }]
6640
6735
  }] });