@leanix/components 0.2.239 → 0.2.240
Sign up to get free protection for your applications and to get access to all the features.
- package/esm2020/index.mjs +3 -1
- package/esm2020/lib/core-ui/core-ui.module.mjs +11 -1
- package/esm2020/lib/core-ui/pipes/linkify/linkify.pipe.mjs +125 -0
- package/esm2020/lib/core-ui/pipes/linkify/unlinkify.pipe.mjs +48 -0
- package/fesm2015/leanix-components.mjs +177 -1
- package/fesm2015/leanix-components.mjs.map +1 -1
- package/fesm2020/leanix-components.mjs +177 -1
- package/fesm2020/leanix-components.mjs.map +1 -1
- package/index.d.ts +2 -0
- package/lib/core-ui/core-ui.module.d.ts +20 -18
- package/lib/core-ui/pipes/linkify/linkify.pipe.d.ts +46 -0
- package/lib/core-ui/pipes/linkify/unlinkify.pipe.d.ts +20 -0
- package/package.json +1 -1
@@ -1142,6 +1142,174 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.5", ngImpor
|
|
1142
1142
|
args: [{ name: 'lxHighlightTerm' }]
|
1143
1143
|
}] });
|
1144
1144
|
|
1145
|
+
/**
|
1146
|
+
* This pipe transforms...
|
1147
|
+
* - "raw" http(s) links
|
1148
|
+
* - markdown link syntax
|
1149
|
+
* ... into clickable anchor elements.
|
1150
|
+
*
|
1151
|
+
* You have an user interface where you don't want clickable links but also
|
1152
|
+
* don't want users to see the "ugly" markdown link syntax?
|
1153
|
+
* -> Use the 'lxUnlikify' pipe to replace markdown link syntax with just the link name
|
1154
|
+
*/
|
1155
|
+
class LxLinkifyPipe {
|
1156
|
+
transform(text) {
|
1157
|
+
if (text && typeof text === 'string') {
|
1158
|
+
let textWithRawLinks = text;
|
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
|
+
});
|
1218
|
+
return textWithRawAndNamedLinks;
|
1219
|
+
}
|
1220
|
+
else {
|
1221
|
+
return text;
|
1222
|
+
}
|
1223
|
+
}
|
1224
|
+
getAllRegexMatches(regex, input) {
|
1225
|
+
let match;
|
1226
|
+
const matches = [];
|
1227
|
+
while ((match = regex.exec(input)) !== null) {
|
1228
|
+
matches.push(match);
|
1229
|
+
}
|
1230
|
+
return matches;
|
1231
|
+
}
|
1232
|
+
}
|
1233
|
+
/**
|
1234
|
+
* This is not the "one URL regex to rule them all", but a more realistic one which should work
|
1235
|
+
* for any URLs that our customers include in text fields on a Fact Sheet.
|
1236
|
+
*
|
1237
|
+
* Regex rules explained in plain text:
|
1238
|
+
*
|
1239
|
+
* (?:(?:https?):\/\/) -> Links must start with "https://" or "http://"
|
1240
|
+
*
|
1241
|
+
* (?:[^\s/$.?#][^\s]*(?<![\.)])) LET'S SPLIT THIS ONE UP
|
1242
|
+
*
|
1243
|
+
* [^\s/$.?#][^\s]* -> Match any legal URL character until the next whitespace
|
1244
|
+
* (?<![\.)] -> A negative lookahead to prevent matching a dot or parenthesis following a URL
|
1245
|
+
*
|
1246
|
+
* Link to regex101: https://regex101.com/r/d3KtfH/1 (NOTE: please update this link when changing the regex)
|
1247
|
+
*/
|
1248
|
+
LxLinkifyPipe.HTTP_LINK_REGEX = /(?:(?:https?):\/\/)(?:[^\s/$.?#][^\s]*)/gi;
|
1249
|
+
/**
|
1250
|
+
* This will match the markdown link syntax: [link name](url)
|
1251
|
+
* Regex rules explained in plain text:
|
1252
|
+
*
|
1253
|
+
* (?:\[([^\]]*)\]) -> Match any characters inside square brackets
|
1254
|
+
* \(([^\s\/$.?#][^\s]*)\) -> Notice that this is the same regex as the HTTP_LINK_REGEX above,
|
1255
|
+
* but without the requirement for the http protocol.
|
1256
|
+
* This allows for links without including the protocol or also "mailto:hello@world.de" links
|
1257
|
+
*
|
1258
|
+
* Link to regex101: https://regex101.com/r/5UMUH8/1
|
1259
|
+
*/
|
1260
|
+
LxLinkifyPipe.NAMED_LINK_REGEX = /(?:\[([^\]]*)\])\(([^\s\/$.?#][^\s]*)\)/gi;
|
1261
|
+
LxLinkifyPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: LxLinkifyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
1262
|
+
LxLinkifyPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: LxLinkifyPipe, name: "lxLinkify" });
|
1263
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: LxLinkifyPipe, decorators: [{
|
1264
|
+
type: Pipe,
|
1265
|
+
args: [{ name: 'lxLinkify' }]
|
1266
|
+
}] });
|
1267
|
+
|
1268
|
+
/**
|
1269
|
+
* This pipe replaces markdown link syntax with just the link name (omits the link altogether).
|
1270
|
+
* Example: [Angular documentation](http://angular.io/docs) -> Angular documentation
|
1271
|
+
*
|
1272
|
+
* It can also be used for "bridging the gap" until your view is ready to use "lxLinkify"
|
1273
|
+
* and you just want to get rid of the "useless" markdown syntax fast.
|
1274
|
+
*
|
1275
|
+
* While there are views where we want markdown style links to be clickable anchor tags,
|
1276
|
+
* there are other views where this can degrade the UX.
|
1277
|
+
* Example: in the Fact Sheet list on the inventory list view, having an arbitrary number
|
1278
|
+
* of links on the page can slow down the keyboard navigation while navigating through the list.
|
1279
|
+
*/
|
1280
|
+
class LxUnlinkifyPipe {
|
1281
|
+
transform(text) {
|
1282
|
+
if (text && typeof text === 'string') {
|
1283
|
+
let textWhereMarkdownLinkSyntaxIsReplacedWithJustTheLinkName = text;
|
1284
|
+
const markdownLinkSyntaxMatches = this.getAllRegexMatches(LxLinkifyPipe.NAMED_LINK_REGEX, text);
|
1285
|
+
markdownLinkSyntaxMatches.forEach((markdownLinkSyntaxMatch) => {
|
1286
|
+
const [source, name] = markdownLinkSyntaxMatch;
|
1287
|
+
if (source && name) {
|
1288
|
+
textWhereMarkdownLinkSyntaxIsReplacedWithJustTheLinkName = textWhereMarkdownLinkSyntaxIsReplacedWithJustTheLinkName.replace(source, name);
|
1289
|
+
}
|
1290
|
+
});
|
1291
|
+
return textWhereMarkdownLinkSyntaxIsReplacedWithJustTheLinkName;
|
1292
|
+
}
|
1293
|
+
else {
|
1294
|
+
return text;
|
1295
|
+
}
|
1296
|
+
}
|
1297
|
+
getAllRegexMatches(regex, input) {
|
1298
|
+
let match;
|
1299
|
+
const matches = [];
|
1300
|
+
while ((match = regex.exec(input)) !== null) {
|
1301
|
+
matches.push(match);
|
1302
|
+
}
|
1303
|
+
return matches;
|
1304
|
+
}
|
1305
|
+
}
|
1306
|
+
LxUnlinkifyPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: LxUnlinkifyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
1307
|
+
LxUnlinkifyPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: LxUnlinkifyPipe, name: "lxUnlinkify" });
|
1308
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.5", ngImport: i0, type: LxUnlinkifyPipe, decorators: [{
|
1309
|
+
type: Pipe,
|
1310
|
+
args: [{ name: 'lxUnlinkify' }]
|
1311
|
+
}] });
|
1312
|
+
|
1145
1313
|
function isUuid(s) {
|
1146
1314
|
const uuidRegEx = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
1147
1315
|
return uuidRegEx.test(s);
|
@@ -1491,6 +1659,8 @@ LxCoreUiModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version:
|
|
1491
1659
|
HighlightTermPipe,
|
1492
1660
|
HtmlDirective,
|
1493
1661
|
IconScaleComponent,
|
1662
|
+
LxLinkifyPipe,
|
1663
|
+
LxUnlinkifyPipe,
|
1494
1664
|
LxTimeAgo,
|
1495
1665
|
LxTranslatePipe,
|
1496
1666
|
MarkdownPipe,
|
@@ -1521,6 +1691,8 @@ LxCoreUiModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version:
|
|
1521
1691
|
HighlightTermPipe,
|
1522
1692
|
HtmlDirective,
|
1523
1693
|
IconScaleComponent,
|
1694
|
+
LxLinkifyPipe,
|
1695
|
+
LxUnlinkifyPipe,
|
1524
1696
|
LxTimeAgo,
|
1525
1697
|
LxTranslatePipe,
|
1526
1698
|
MarkdownPipe,
|
@@ -1558,6 +1730,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.5", ngImpor
|
|
1558
1730
|
HighlightTermPipe,
|
1559
1731
|
HtmlDirective,
|
1560
1732
|
IconScaleComponent,
|
1733
|
+
LxLinkifyPipe,
|
1734
|
+
LxUnlinkifyPipe,
|
1561
1735
|
LxTimeAgo,
|
1562
1736
|
LxTranslatePipe,
|
1563
1737
|
MarkdownPipe,
|
@@ -1592,6 +1766,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.5", ngImpor
|
|
1592
1766
|
HighlightTermPipe,
|
1593
1767
|
HtmlDirective,
|
1594
1768
|
IconScaleComponent,
|
1769
|
+
LxLinkifyPipe,
|
1770
|
+
LxUnlinkifyPipe,
|
1595
1771
|
LxTimeAgo,
|
1596
1772
|
LxTranslatePipe,
|
1597
1773
|
MarkdownPipe,
|
@@ -6301,5 +6477,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.5", ngImpor
|
|
6301
6477
|
* Generated bundle index. Do not edit.
|
6302
6478
|
*/
|
6303
6479
|
|
6304
|
-
export { ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, AfterViewInitDirective, AutocloseDirective, AutofocusDirective, BACKSPACE, BadgeComponent, BaseSelectDirective, BasicDropdownComponent, BasicDropdownItemComponent, BrPipe, ButtonComponent, ButtonGroupComponent, CURRENCY_SYMBOL_MAP, CardComponent, CdkOptionsDropdownComponent, CdkOptionsSubDropdownComponent, CollapsibleComponent, ColoredLabelComponent, ContrastColorPipe, CurrencyInputComponent, CurrencySymbolComponent, CustomDatePipe, DATE_FN_LOCALE, DATE_FORMATS, DateInputComponent, DragAndDropListComponent, DragAndDropListItemComponent, ENTER, ESCAPE, EllipsisComponent, ErrorMessageComponent, FORM_CONTROL_ERROR_DISPLAY_STRATEGY, FORM_CONTROL_ERROR_NAMESPACE, FilterSelectionPipe, FilterTermPipe, FormErrorComponent, FormErrorDirective, FormSubmitDirective, FormatNumberPipe, GLOBAL_TRANSLATION_OPTIONS, HighlightRangePipe, HighlightTermPipe, HtmlDirective, IconComponent, IconScaleComponent, KeyboardActionSourceDirective, KeyboardSelectAction, KeyboardSelectDirective, LOCALE_FN, LX_ELLIPSIS_DEBOUNCE_ON_RESIZE, LxCoreUiModule, LxDragAndDropListModule, LxFormsModule, LxIsUuidPipe, LxModalModule, LxPopoverUiModule, LxTabUiModule, LxTimeAgo, LxTooltipModule, LxTranslatePipe, MODAL_CLOSE, MarkInvalidDirective, MarkdownPipe, ModalComponent, ModalContentDirective, ModalFooterComponent, ModalHeaderComponent, MultiSelectComponent, NbspPipe, OptionComponent, OptionGroupComponent, OptionGroupDropdownComponent, OptionsDropdownComponent, OptionsSubDropdownComponent, PickerComponent, PickerOptionComponent, PickerTriggerDirective, PillItemComponent, PillListComponent, PopoverClickDirective, PopoverComponent, PopoverContentDirective, PopoverHoverDirective, Required, ResizeObserverService, ResponsiveInputComponent, SPACE, SelectDropdownDirective, SelectableItemDirective, SelectedOptionDirective, SingleSelectComponent, SliderToggleComponent, SortPipe, Sorting, SortingDropdownComponent, SortingDropdownTriggerComponent, SpinnerComponent, TAB, TabComponent, TabGroupComponent, TableComponent, TableHeaderComponent, TinySpinnerComponent, TooltipComponent, TooltipDirective, TranslationAfterPipe, TranslationBeforePipe, TranslationBetweenPipe, UnescapeCurlyBracesPipe, ValidateDateInForeseeableFuture, getContrastColor, getTranslationParts, isValidHexColor, isValidX, isValidY, provideFormControlErrorDisplayStrategy, provideFormControlErrorNamespace, shorthandHexHandle };
|
6480
|
+
export { ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, AfterViewInitDirective, AutocloseDirective, AutofocusDirective, BACKSPACE, BadgeComponent, BaseSelectDirective, BasicDropdownComponent, BasicDropdownItemComponent, BrPipe, ButtonComponent, ButtonGroupComponent, CURRENCY_SYMBOL_MAP, CardComponent, CdkOptionsDropdownComponent, CdkOptionsSubDropdownComponent, CollapsibleComponent, ColoredLabelComponent, ContrastColorPipe, CurrencyInputComponent, CurrencySymbolComponent, CustomDatePipe, DATE_FN_LOCALE, DATE_FORMATS, DateInputComponent, DragAndDropListComponent, DragAndDropListItemComponent, ENTER, ESCAPE, EllipsisComponent, ErrorMessageComponent, FORM_CONTROL_ERROR_DISPLAY_STRATEGY, FORM_CONTROL_ERROR_NAMESPACE, FilterSelectionPipe, FilterTermPipe, FormErrorComponent, FormErrorDirective, FormSubmitDirective, FormatNumberPipe, GLOBAL_TRANSLATION_OPTIONS, HighlightRangePipe, HighlightTermPipe, HtmlDirective, IconComponent, IconScaleComponent, KeyboardActionSourceDirective, KeyboardSelectAction, KeyboardSelectDirective, LOCALE_FN, LX_ELLIPSIS_DEBOUNCE_ON_RESIZE, LxCoreUiModule, LxDragAndDropListModule, LxFormsModule, LxIsUuidPipe, LxLinkifyPipe, LxModalModule, LxPopoverUiModule, LxTabUiModule, LxTimeAgo, LxTooltipModule, LxTranslatePipe, LxUnlinkifyPipe, MODAL_CLOSE, MarkInvalidDirective, MarkdownPipe, ModalComponent, ModalContentDirective, ModalFooterComponent, ModalHeaderComponent, MultiSelectComponent, NbspPipe, OptionComponent, OptionGroupComponent, OptionGroupDropdownComponent, OptionsDropdownComponent, OptionsSubDropdownComponent, PickerComponent, PickerOptionComponent, PickerTriggerDirective, PillItemComponent, PillListComponent, PopoverClickDirective, PopoverComponent, PopoverContentDirective, PopoverHoverDirective, Required, ResizeObserverService, ResponsiveInputComponent, SPACE, SelectDropdownDirective, SelectableItemDirective, SelectedOptionDirective, SingleSelectComponent, SliderToggleComponent, SortPipe, Sorting, SortingDropdownComponent, SortingDropdownTriggerComponent, SpinnerComponent, TAB, TabComponent, TabGroupComponent, TableComponent, TableHeaderComponent, TinySpinnerComponent, TooltipComponent, TooltipDirective, TranslationAfterPipe, TranslationBeforePipe, TranslationBetweenPipe, UnescapeCurlyBracesPipe, ValidateDateInForeseeableFuture, getContrastColor, getTranslationParts, isValidHexColor, isValidX, isValidY, provideFormControlErrorDisplayStrategy, provideFormControlErrorNamespace, shorthandHexHandle };
|
6305
6481
|
//# sourceMappingURL=leanix-components.mjs.map
|