@leanix/components 0.2.239 → 0.2.240
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.
- 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
|