@leanix/components 0.2.240 → 0.2.243
Sign up to get free protection for your applications and to get access to all the features.
- package/esm2020/lib/core-ui/pipes/linkify/linkify.pipe.mjs +66 -61
- package/esm2020/lib/core-ui/services/resize-observer.service.mjs +51 -2
- package/fesm2015/leanix-components.mjs +112 -62
- package/fesm2015/leanix-components.mjs.map +1 -1
- package/fesm2020/leanix-components.mjs +115 -62
- package/fesm2020/leanix-components.mjs.map +1 -1
- package/lib/core-ui/pipes/linkify/linkify.pipe.d.ts +2 -0
- package/lib/core-ui/services/resize-observer.service.d.ts +8 -0
- package/package.json +1 -1
@@ -8,7 +8,7 @@ import * as i1 from '@angular/cdk/overlay';
|
|
8
8
|
import { OverlayModule, CdkConnectedOverlay } from '@angular/cdk/overlay';
|
9
9
|
import { __decorate } from 'tslib';
|
10
10
|
import * as i6 from 'rxjs';
|
11
|
-
import { BehaviorSubject, Subject, combineLatest, merge, concat, fromEvent, Observable, ReplaySubject, of
|
11
|
+
import { BehaviorSubject, timer, Subject, combineLatest, merge, concat, fromEvent, Observable, ReplaySubject, of } from 'rxjs';
|
12
12
|
import { skipWhile, map, switchMap, startWith, pairwise, filter, take, debounceTime, skip, withLatestFrom, distinctUntilChanged, takeUntil, first, delay, mapTo, tap } from 'rxjs/operators';
|
13
13
|
import * as i1$1 from '@ngx-translate/core';
|
14
14
|
import { TranslatePipe, TranslateModule } from '@ngx-translate/core';
|
@@ -513,7 +513,16 @@ function isResizeableElement(element) {
|
|
513
513
|
class ResizeObserverService {
|
514
514
|
observe(element, callback, options) {
|
515
515
|
if (!this.resizeObserver) {
|
516
|
-
|
516
|
+
try {
|
517
|
+
this.resizeObserver = new ResizeObserver(this.resizeObserverCallback.bind(this));
|
518
|
+
}
|
519
|
+
catch {
|
520
|
+
// All the browsers we support implement the ResizeObserver API.
|
521
|
+
// For unsupported browsers, there's this "one time artifical resize event".
|
522
|
+
// They will not get the functionality tied to later resize events.
|
523
|
+
timer(500).subscribe(() => callback(this.getMockOneTimeResizeEventForUnsupportedBrowsers(element)));
|
524
|
+
return;
|
525
|
+
}
|
517
526
|
}
|
518
527
|
element.handleResize = callback;
|
519
528
|
this.resizeObserver.observe(element, options);
|
@@ -531,6 +540,45 @@ class ResizeObserverService {
|
|
531
540
|
}
|
532
541
|
});
|
533
542
|
}
|
543
|
+
/**
|
544
|
+
* All browsers we officially support implement the ResizeObserver API.
|
545
|
+
* Still as a curtesy do customers who for some reason have older browsers
|
546
|
+
* we call the callback once with the initial dimensions of the element
|
547
|
+
* and then do not react on resize events afterwards.
|
548
|
+
* This should still make them happier than a "browser not supported" warning.
|
549
|
+
*/
|
550
|
+
getMockOneTimeResizeEventForUnsupportedBrowsers(element) {
|
551
|
+
const contentRect = {
|
552
|
+
bottom: element.clientHeight,
|
553
|
+
height: element.clientHeight,
|
554
|
+
left: 0,
|
555
|
+
right: element.clientWidth,
|
556
|
+
top: 0,
|
557
|
+
width: element.clientWidth,
|
558
|
+
x: 0,
|
559
|
+
y: 0
|
560
|
+
};
|
561
|
+
return {
|
562
|
+
borderBoxSize: [{ blockSize: element.clientHeight, inlineSize: element.clientWidth }],
|
563
|
+
contentBoxSize: [
|
564
|
+
{
|
565
|
+
blockSize: element.clientHeight,
|
566
|
+
inlineSize: element.clientWidth
|
567
|
+
}
|
568
|
+
],
|
569
|
+
contentRect: {
|
570
|
+
...contentRect,
|
571
|
+
toJSON: () => JSON.stringify(contentRect)
|
572
|
+
},
|
573
|
+
devicePixelContentBoxSize: [
|
574
|
+
{
|
575
|
+
blockSize: element.clientWidth,
|
576
|
+
inlineSize: element.clientWidth
|
577
|
+
}
|
578
|
+
],
|
579
|
+
target: element
|
580
|
+
};
|
581
|
+
}
|
534
582
|
}
|
535
583
|
ResizeObserverService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: ResizeObserverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
536
584
|
ResizeObserverService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: ResizeObserverService, providedIn: 'root' });
|
@@ -1155,72 +1203,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.5", ngImpor
|
|
1155
1203
|
class LxLinkifyPipe {
|
1156
1204
|
transform(text) {
|
1157
1205
|
if (text && typeof text === 'string') {
|
1158
|
-
|
1159
|
-
|
1160
|
-
* Keeping track of this index prevents infinite loops
|
1161
|
-
* where a previously processed link starts with the same characters
|
1162
|
-
* as a second link.
|
1163
|
-
* e.g. https://angular.io/docs followed by https://angular.io
|
1164
|
-
*/
|
1165
|
-
let nextIndexToStartReplacingFrom = 0;
|
1166
|
-
const rawLinkMatches = this.getAllRegexMatches(LxLinkifyPipe.HTTP_LINK_REGEX, text);
|
1167
|
-
rawLinkMatches.forEach((rawLinkMatch) => {
|
1168
|
-
const [url] = rawLinkMatch;
|
1169
|
-
const wrapUrlInAnchor = (sanitizedUrlMatch) => {
|
1170
|
-
const firstPart = textWithRawLinks.substring(0, nextIndexToStartReplacingFrom);
|
1171
|
-
const anchorTagHtml = `<a href="${sanitizedUrlMatch}" target="_blank" rel="noopener noreferrer">${sanitizedUrlMatch}</a>`;
|
1172
|
-
const secondPart = textWithRawLinks.substring(nextIndexToStartReplacingFrom).replace(sanitizedUrlMatch, anchorTagHtml);
|
1173
|
-
textWithRawLinks = firstPart + secondPart;
|
1174
|
-
nextIndexToStartReplacingFrom = rawLinkMatch.index + anchorTagHtml.length;
|
1175
|
-
};
|
1176
|
-
if (url) {
|
1177
|
-
/*
|
1178
|
-
* TODO: get rid of all this code once Safari supports negative lookbehinds in regular expressions
|
1179
|
-
* The following is RegExp that handles the same stuff as the JS code below:
|
1180
|
-
*
|
1181
|
-
* /(?:(?:(?<!\]\())(?:https|http):\/\/)(?:[^\s/$.?#][^\s]*(?<![\.)]))/gi;
|
1182
|
-
*
|
1183
|
-
* Demo on regex101: https://regex101.com/r/7Vl9bg/1
|
1184
|
-
*
|
1185
|
-
* Check lookbehind support here: https://caniuse.com/?search=lookbehind
|
1186
|
-
*/
|
1187
|
-
const lastUrlCharacterIndex = rawLinkMatch.index + url.length - 1;
|
1188
|
-
const textUsedToPerformMatching = rawLinkMatch.input;
|
1189
|
-
const lastCharacterInUrl = textUsedToPerformMatching[lastUrlCharacterIndex];
|
1190
|
-
if (lastCharacterInUrl === '.') {
|
1191
|
-
const characterAfterUrl = textUsedToPerformMatching[lastUrlCharacterIndex + 1];
|
1192
|
-
if (!characterAfterUrl || characterAfterUrl === ' ' || characterAfterUrl === '\n') {
|
1193
|
-
const urlWithoutDotAtTheEnd = url.slice(0, -1);
|
1194
|
-
wrapUrlInAnchor(urlWithoutDotAtTheEnd);
|
1195
|
-
}
|
1196
|
-
}
|
1197
|
-
else if (rawLinkMatch.index > 3) {
|
1198
|
-
const twoCharactersInFrontOfTheLink = `${textUsedToPerformMatching[rawLinkMatch.index - 2]}${textUsedToPerformMatching[rawLinkMatch.index - 1]}`;
|
1199
|
-
if (twoCharactersInFrontOfTheLink && twoCharactersInFrontOfTheLink !== '](') {
|
1200
|
-
// only wrap url in anchor when it is not a named markdown link
|
1201
|
-
wrapUrlInAnchor(url);
|
1202
|
-
}
|
1203
|
-
}
|
1204
|
-
else {
|
1205
|
-
wrapUrlInAnchor(url);
|
1206
|
-
}
|
1207
|
-
}
|
1208
|
-
});
|
1209
|
-
let textWithRawAndNamedLinks = textWithRawLinks;
|
1210
|
-
const namedLinkMatches = this.getAllRegexMatches(LxLinkifyPipe.NAMED_LINK_REGEX, textWithRawLinks);
|
1211
|
-
namedLinkMatches.forEach((namedLinkMatch) => {
|
1212
|
-
const [source, name, url] = namedLinkMatch;
|
1213
|
-
const urlIsValid = url && !/javascript\:/i.test(url);
|
1214
|
-
if (source && name && urlIsValid) {
|
1215
|
-
textWithRawAndNamedLinks = textWithRawAndNamedLinks.replace(source, `<a href="${url}" target="_blank" rel="noopener noreferrer">${name}</a>`);
|
1216
|
-
}
|
1217
|
-
});
|
1206
|
+
const textWithRawLinks = this.wrapRawHttpLinksWithAnchorTags(text);
|
1207
|
+
const textWithRawAndNamedLinks = this.turnMarkdownStyleLinksIntoAnchorTags(textWithRawLinks);
|
1218
1208
|
return textWithRawAndNamedLinks;
|
1219
1209
|
}
|
1220
1210
|
else {
|
1221
1211
|
return text;
|
1222
1212
|
}
|
1223
1213
|
}
|
1214
|
+
turnMarkdownStyleLinksIntoAnchorTags(text) {
|
1215
|
+
let textWithRawAndNamedLinks = text;
|
1216
|
+
const namedLinkMatches = this.getAllRegexMatches(LxLinkifyPipe.NAMED_LINK_REGEX, text);
|
1217
|
+
namedLinkMatches.forEach((namedLinkMatch) => {
|
1218
|
+
const [source, name, url] = namedLinkMatch;
|
1219
|
+
const urlIsValid = url && !/javascript\:/i.test(url);
|
1220
|
+
if (source && name && urlIsValid) {
|
1221
|
+
textWithRawAndNamedLinks = textWithRawAndNamedLinks.replace(source, `<a href="${url}" target="_blank" rel="noopener noreferrer">${name}</a>`);
|
1222
|
+
}
|
1223
|
+
});
|
1224
|
+
return textWithRawAndNamedLinks;
|
1225
|
+
}
|
1226
|
+
wrapRawHttpLinksWithAnchorTags(text) {
|
1227
|
+
let textWithRawLinks = text;
|
1228
|
+
/**
|
1229
|
+
* Keeping track of this index prevents infinite loops
|
1230
|
+
* where a previously processed link starts with the same characters
|
1231
|
+
* as a second link.
|
1232
|
+
* e.g. https://angular.io/docs followed by https://angular.io
|
1233
|
+
*/
|
1234
|
+
let nextIndexToStartReplacingFrom = 0;
|
1235
|
+
const rawLinkMatches = this.getAllRegexMatches(LxLinkifyPipe.HTTP_LINK_REGEX, text);
|
1236
|
+
rawLinkMatches.forEach((rawLinkMatch) => {
|
1237
|
+
const [url] = rawLinkMatch;
|
1238
|
+
const wrapUrlInAnchor = (sanitizedUrlMatch) => {
|
1239
|
+
const firstPart = textWithRawLinks.substring(0, nextIndexToStartReplacingFrom);
|
1240
|
+
const anchorTagHtml = `<a href="${sanitizedUrlMatch}" target="_blank" rel="noopener noreferrer">${sanitizedUrlMatch}</a>`;
|
1241
|
+
const secondPart = textWithRawLinks.substring(nextIndexToStartReplacingFrom).replace(sanitizedUrlMatch, anchorTagHtml);
|
1242
|
+
textWithRawLinks = firstPart + secondPart;
|
1243
|
+
nextIndexToStartReplacingFrom = rawLinkMatch.index + anchorTagHtml.length;
|
1244
|
+
};
|
1245
|
+
if (url) {
|
1246
|
+
/*
|
1247
|
+
* TODO: get rid of all this code once Safari supports negative lookbehinds in regular expressions
|
1248
|
+
* The following is RegExp that handles the same stuff as the JS code below:
|
1249
|
+
*
|
1250
|
+
* /(?:(?:(?<!\]\())(?:https|http):\/\/)(?:[^\s/$.?#][^\s]*(?<![\.)]))/gi;
|
1251
|
+
*
|
1252
|
+
* Demo on regex101: https://regex101.com/r/7Vl9bg/1
|
1253
|
+
*
|
1254
|
+
* Check lookbehind support here: https://caniuse.com/?search=lookbehind
|
1255
|
+
*/
|
1256
|
+
const lastUrlCharacterIndex = rawLinkMatch.index + url.length - 1;
|
1257
|
+
const textUsedToPerformMatching = rawLinkMatch.input;
|
1258
|
+
const lastCharacterInUrl = textUsedToPerformMatching[lastUrlCharacterIndex];
|
1259
|
+
const twoCharactersInFrontOfTheLink = rawLinkMatch.index > 3
|
1260
|
+
? `${textUsedToPerformMatching[rawLinkMatch.index - 2]}${textUsedToPerformMatching[rawLinkMatch.index - 1]}`
|
1261
|
+
: '';
|
1262
|
+
const isMarkdownSyntaxLink = twoCharactersInFrontOfTheLink === '](';
|
1263
|
+
if (!isMarkdownSyntaxLink && lastCharacterInUrl === '.') {
|
1264
|
+
const characterAfterUrl = textUsedToPerformMatching[lastUrlCharacterIndex + 1];
|
1265
|
+
if (!characterAfterUrl || characterAfterUrl === ' ' || characterAfterUrl === '\n') {
|
1266
|
+
const urlWithoutDotAtTheEnd = url.slice(0, -1);
|
1267
|
+
wrapUrlInAnchor(urlWithoutDotAtTheEnd);
|
1268
|
+
}
|
1269
|
+
}
|
1270
|
+
else if (!isMarkdownSyntaxLink) {
|
1271
|
+
wrapUrlInAnchor(url);
|
1272
|
+
}
|
1273
|
+
}
|
1274
|
+
});
|
1275
|
+
return textWithRawLinks;
|
1276
|
+
}
|
1224
1277
|
getAllRegexMatches(regex, input) {
|
1225
1278
|
let match;
|
1226
1279
|
const matches = [];
|