mirror of https://github.com/keeweb/keeweb.git
entry selection filters
This commit is contained in:
parent
95857450c2
commit
732c35625b
|
@ -6,7 +6,10 @@ const urlPartsRegex = /^(\w+:\/\/)?(?:(?:www|wwws|secure)\.)?([^\/]+)\/?(.*)/;
|
||||||
class SelectEntryFilter {
|
class SelectEntryFilter {
|
||||||
constructor(windowInfo, appModel, files, filterOptions) {
|
constructor(windowInfo, appModel, files, filterOptions) {
|
||||||
this.title = windowInfo.title;
|
this.title = windowInfo.title;
|
||||||
|
this.useTitle = !!windowInfo.title && !windowInfo.url;
|
||||||
this.url = windowInfo.url;
|
this.url = windowInfo.url;
|
||||||
|
this.useUrl = !!windowInfo.url;
|
||||||
|
this.subdomains = true;
|
||||||
this.text = '';
|
this.text = '';
|
||||||
this.appModel = appModel;
|
this.appModel = appModel;
|
||||||
this.files = files;
|
this.files = files;
|
||||||
|
@ -22,7 +25,9 @@ class SelectEntryFilter {
|
||||||
let entries = this.appModel
|
let entries = this.appModel
|
||||||
.getEntriesByFilter(filter, this.files)
|
.getEntriesByFilter(filter, this.files)
|
||||||
.map((e) => [e, this._getEntryRank(e)]);
|
.map((e) => [e, this._getEntryRank(e)]);
|
||||||
entries = entries.filter((e) => e[1]);
|
if (this.useUrl || this.useTitle) {
|
||||||
|
entries = entries.filter((e) => e[1]);
|
||||||
|
}
|
||||||
entries = entries.sort((x, y) =>
|
entries = entries.sort((x, y) =>
|
||||||
x[1] === y[1] ? x[0].title.localeCompare(y[0].title) : y[1] - x[1]
|
x[1] === y[1] ? x[0].title.localeCompare(y[0].title) : y[1] - x[1]
|
||||||
);
|
);
|
||||||
|
@ -37,52 +42,68 @@ class SelectEntryFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
_getEntryRank(entry) {
|
_getEntryRank(entry) {
|
||||||
let rank = 0;
|
let titleRank = 0;
|
||||||
if (this.titleLower && entry.title) {
|
let urlRank = 0;
|
||||||
rank += Ranking.getStringRank(entry.title.toLowerCase(), this.titleLower);
|
|
||||||
|
if (this.useTitle && this.titleLower && entry.title) {
|
||||||
|
titleRank = Ranking.getStringRank(entry.title.toLowerCase(), this.titleLower);
|
||||||
|
if (!titleRank) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.urlParts) {
|
|
||||||
|
if (this.useUrl && this.urlParts) {
|
||||||
if (entry.url) {
|
if (entry.url) {
|
||||||
const entryUrlParts = urlPartsRegex.exec(entry.url.toLowerCase());
|
const entryUrlParts = urlPartsRegex.exec(entry.url.toLowerCase());
|
||||||
if (entryUrlParts) {
|
if (entryUrlParts) {
|
||||||
const [, scheme, domain, path] = entryUrlParts;
|
const [, scheme, domain, path] = entryUrlParts;
|
||||||
const [, thisScheme, thisDomain, thisPath] = this.urlParts;
|
const [, thisScheme, thisDomain, thisPath] = this.urlParts;
|
||||||
if (domain === thisDomain || thisDomain.indexOf('.' + domain) > 0) {
|
if (
|
||||||
|
domain === thisDomain ||
|
||||||
|
(this.subdomains && thisDomain.indexOf('.' + domain) > 0)
|
||||||
|
) {
|
||||||
if (domain === thisDomain) {
|
if (domain === thisDomain) {
|
||||||
rank += 20;
|
urlRank += 20;
|
||||||
} else {
|
} else {
|
||||||
rank += 10;
|
urlRank += 10;
|
||||||
}
|
}
|
||||||
if (path === thisPath) {
|
if (path === thisPath) {
|
||||||
rank += 10;
|
urlRank += 10;
|
||||||
} else if (path && thisPath) {
|
} else if (path && thisPath) {
|
||||||
if (path.lastIndexOf(thisPath, 0) === 0) {
|
if (path.lastIndexOf(thisPath, 0) === 0) {
|
||||||
rank += 5;
|
urlRank += 5;
|
||||||
} else if (thisPath.lastIndexOf(path, 0) === 0) {
|
} else if (thisPath.lastIndexOf(path, 0) === 0) {
|
||||||
rank += 3;
|
urlRank += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scheme === thisScheme) {
|
if (scheme === thisScheme) {
|
||||||
rank += 1;
|
urlRank += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (entry.searchText.indexOf(this.urlLower) >= 0) {
|
if (entry.searchText.indexOf(this.urlLower) >= 0) {
|
||||||
// the url is in some field; include it
|
// the url is in some field; include it
|
||||||
rank += 5;
|
urlRank += 5;
|
||||||
} else {
|
} else {
|
||||||
// another domain; don't show this record at all, ignore title match
|
// another domain; don't show this record at all
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (entry.searchText.indexOf(this.urlLower) >= 0) {
|
if (entry.searchText.indexOf(this.urlLower) >= 0) {
|
||||||
// the url is in some field; include it
|
// the url is in some field; include it
|
||||||
rank += 5;
|
urlRank += 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rank;
|
|
||||||
|
if (this.useTitle && !titleRank) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (this.useUrl && !urlRank) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return titleRank + urlRank;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -803,5 +803,8 @@
|
||||||
|
|
||||||
"selectEntryHeader": "Select entry",
|
"selectEntryHeader": "Select entry",
|
||||||
"selectEntryEnterHint": "use the highlighted entry",
|
"selectEntryEnterHint": "use the highlighted entry",
|
||||||
"selectEntryEscHint": "cancel"
|
"selectEntryEscHint": "cancel",
|
||||||
|
"selectEntryTypingHint": "Start typing to filter",
|
||||||
|
"selectEntryContains": "Contains text",
|
||||||
|
"selectEntrySubdomains": "Subdomains"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ const UrlFormat = {
|
||||||
multiSlashRegex: /\/{2,}/g,
|
multiSlashRegex: /\/{2,}/g,
|
||||||
lastPartRegex: /[\/\\]?[^\/\\]+$/,
|
lastPartRegex: /[\/\\]?[^\/\\]+$/,
|
||||||
kdbxEndRegex: /\.kdbx$/i,
|
kdbxEndRegex: /\.kdbx$/i,
|
||||||
|
maxShortPresentableUrlLength: 60,
|
||||||
|
|
||||||
getDataFileName(url) {
|
getDataFileName(url) {
|
||||||
const ix = url.lastIndexOf('/');
|
const ix = url.lastIndexOf('/');
|
||||||
|
@ -35,6 +36,36 @@ const UrlFormat = {
|
||||||
return Object.entries(params)
|
return Object.entries(params)
|
||||||
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
|
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
|
||||||
.join('&');
|
.join('&');
|
||||||
|
},
|
||||||
|
|
||||||
|
presentAsShortUrl(url) {
|
||||||
|
if (url.length <= this.maxShortPresentableUrlLength) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [beforeHash] = url.split('#', 1);
|
||||||
|
if (beforeHash.length <= this.maxShortPresentableUrlLength) {
|
||||||
|
return beforeHash + '#…';
|
||||||
|
}
|
||||||
|
|
||||||
|
const [beforeQuestionMark] = url.split('?', 1);
|
||||||
|
if (beforeQuestionMark.length <= this.maxShortPresentableUrlLength) {
|
||||||
|
return beforeQuestionMark + '?…';
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = new URL(beforeQuestionMark);
|
||||||
|
const pathParts = parsed.pathname.split('/');
|
||||||
|
|
||||||
|
while (pathParts.length > 1) {
|
||||||
|
pathParts.pop();
|
||||||
|
parsed.pathname = pathParts.join('/');
|
||||||
|
const res = parsed.toString();
|
||||||
|
if (res.length < this.maxShortPresentableUrlLength) {
|
||||||
|
return res + '/…';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed + '…';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Keys } from 'const/keys';
|
||||||
import { AppSettingsModel } from 'models/app-settings-model';
|
import { AppSettingsModel } from 'models/app-settings-model';
|
||||||
import { EntryPresenter } from 'presenters/entry-presenter';
|
import { EntryPresenter } from 'presenters/entry-presenter';
|
||||||
import { StringFormat } from 'util/formatting/string-format';
|
import { StringFormat } from 'util/formatting/string-format';
|
||||||
|
import { UrlFormat } from 'util/formatting/url-format';
|
||||||
import { Locale } from 'util/locale';
|
import { Locale } from 'util/locale';
|
||||||
import { Scrollable } from 'framework/views/scrollable';
|
import { Scrollable } from 'framework/views/scrollable';
|
||||||
import { DropdownView } from 'views/dropdown-view';
|
import { DropdownView } from 'views/dropdown-view';
|
||||||
|
@ -23,7 +24,8 @@ class SelectEntryView extends View {
|
||||||
events = {
|
events = {
|
||||||
'click .select-entry__header-filter-clear': 'clearFilterText',
|
'click .select-entry__header-filter-clear': 'clearFilterText',
|
||||||
'click .select-entry__item': 'itemClicked',
|
'click .select-entry__item': 'itemClicked',
|
||||||
'contextmenu .select-entry__item': 'itemRightClicked'
|
'contextmenu .select-entry__item': 'itemRightClicked',
|
||||||
|
'click .select-entry__filter': 'filterClicked'
|
||||||
};
|
};
|
||||||
|
|
||||||
result = null;
|
result = null;
|
||||||
|
@ -73,10 +75,13 @@ class SelectEntryView extends View {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const noColor = AppSettingsModel.colorfulIcons ? '' : 'grayscale';
|
const noColor = AppSettingsModel.colorfulIcons ? '' : 'grayscale';
|
||||||
this.entries = this.model.filter.getEntries();
|
|
||||||
this.result = this.entries[0];
|
|
||||||
|
|
||||||
const presenter = new EntryPresenter(null, noColor, this.result && this.result.id);
|
this.entries = this.model.filter.getEntries();
|
||||||
|
if (!this.result || !this.entries.includes(this.result)) {
|
||||||
|
this.result = this.entries[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const presenter = new EntryPresenter(null, noColor, this.result?.id);
|
||||||
presenter.itemOptions = this.model.itemOptions;
|
presenter.itemOptions = this.model.itemOptions;
|
||||||
|
|
||||||
let itemsHtml = '';
|
let itemsHtml = '';
|
||||||
|
@ -86,10 +91,43 @@ class SelectEntryView extends View {
|
||||||
itemsHtml += itemTemplate(presenter, DefaultTemplateOptions);
|
itemsHtml += itemTemplate(presenter, DefaultTemplateOptions);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filters = [];
|
||||||
|
if (this.model.filter.url) {
|
||||||
|
const shortUrl = UrlFormat.presentAsShortUrl(this.model.filter.url);
|
||||||
|
filters.push({
|
||||||
|
id: 'url',
|
||||||
|
type: StringFormat.capFirst(Locale.website),
|
||||||
|
text: shortUrl,
|
||||||
|
active: this.model.filter.useUrl
|
||||||
|
});
|
||||||
|
|
||||||
|
filters.push({
|
||||||
|
id: 'subdomains',
|
||||||
|
type: StringFormat.capFirst(Locale.selectEntrySubdomains),
|
||||||
|
active: this.model.filter.useUrl && this.model.filter.subdomains
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.model.filter.title) {
|
||||||
|
filters.push({
|
||||||
|
id: 'title',
|
||||||
|
type: StringFormat.capFirst(Locale.title),
|
||||||
|
text: this.model.filter.title,
|
||||||
|
active: this.model.filter.useTitle
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.model.filter.text) {
|
||||||
|
filters.push({
|
||||||
|
id: 'text',
|
||||||
|
type: StringFormat.capFirst(Locale.selectEntryContains),
|
||||||
|
text: this.model.filter.text,
|
||||||
|
active: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
super.render({
|
super.render({
|
||||||
isAutoType: this.model.isAutoType,
|
isAutoType: this.model.isAutoType,
|
||||||
filterText: this.model.filter.text,
|
|
||||||
topMessage: this.model.topMessage,
|
topMessage: this.model.topMessage,
|
||||||
|
filters,
|
||||||
itemsHtml,
|
itemsHtml,
|
||||||
actionSymbol: Shortcuts.actionShortcutSymbol(true),
|
actionSymbol: Shortcuts.actionShortcutSymbol(true),
|
||||||
altSymbol: Shortcuts.altShortcutSymbol(true),
|
altSymbol: Shortcuts.altShortcutSymbol(true),
|
||||||
|
@ -192,18 +230,10 @@ class SelectEntryView extends View {
|
||||||
|
|
||||||
backSpacePressed() {
|
backSpacePressed() {
|
||||||
if (this.model.filter.text) {
|
if (this.model.filter.text) {
|
||||||
const input = this.el.querySelector('.select-entry__header-filter-input');
|
this.model.filter.text = this.model.filter.text.substr(
|
||||||
if (input.selectionStart < input.selectionEnd) {
|
0,
|
||||||
this.model.filter.text =
|
this.model.filter.text.length - 1
|
||||||
this.model.filter.text.substr(0, input.selectionStart) +
|
);
|
||||||
this.model.filter.text.substr(input.selectionEnd);
|
|
||||||
input.selectionStart = input.selectionEnd = 0;
|
|
||||||
} else {
|
|
||||||
this.model.filter.text = this.model.filter.text.substr(
|
|
||||||
0,
|
|
||||||
this.model.filter.text.length - 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,6 +366,34 @@ class SelectEntryView extends View {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterClicked(e) {
|
||||||
|
const filterEl = e.target.closest('.select-entry__filter');
|
||||||
|
const filter = filterEl.dataset.filter;
|
||||||
|
const active = filterEl.dataset.active !== 'true';
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case 'url':
|
||||||
|
this.model.filter.useUrl = active;
|
||||||
|
break;
|
||||||
|
case 'subdomains':
|
||||||
|
this.model.filter.subdomains = active;
|
||||||
|
if (active) {
|
||||||
|
this.model.filter.useUrl = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'title':
|
||||||
|
this.model.filter.useTitle = active;
|
||||||
|
break;
|
||||||
|
case 'text':
|
||||||
|
if (!active) {
|
||||||
|
this.model.filter.text = '';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(SelectEntryView.prototype, Scrollable);
|
Object.assign(SelectEntryView.prototype, Scrollable);
|
||||||
|
|
|
@ -27,19 +27,6 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding-right: $base-padding-h;
|
padding-right: $base-padding-h;
|
||||||
}
|
}
|
||||||
&-filter {
|
|
||||||
flex: auto 0;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
&-filter-input {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
&-filter-clear {
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
right: 0.7em;
|
|
||||||
top: 0.5em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&__message {
|
&__message {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -129,4 +116,32 @@
|
||||||
&__empty-title {
|
&__empty-title {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
&__filters {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
&__filter {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: $small-spacing;
|
||||||
|
margin-right: $small-spacing;
|
||||||
|
border-radius: var(--button-border-radius);
|
||||||
|
background-color: var(--unselected-background-color);
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--unselected-background-color-hover);
|
||||||
|
}
|
||||||
|
&-text,
|
||||||
|
&-icon {
|
||||||
|
padding: $base-padding;
|
||||||
|
}
|
||||||
|
&-check {
|
||||||
|
font-size: 1.2em;
|
||||||
|
padding: 0.35em 0 0 $base-padding-h;
|
||||||
|
}
|
||||||
|
&-text {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,3 +204,4 @@ $fa-var-window-maximize: next-fa-glyph();
|
||||||
$fa-var-download: next-fa-glyph();
|
$fa-var-download: next-fa-glyph();
|
||||||
$fa-var-exchange-alt: next-fa-glyph();
|
$fa-var-exchange-alt: next-fa-glyph();
|
||||||
$fa-var-folder-plus: next-fa-glyph();
|
$fa-var-folder-plus: next-fa-glyph();
|
||||||
|
$fa-var-filter: next-fa-glyph();
|
||||||
|
|
|
@ -53,6 +53,10 @@
|
||||||
intermediate-pressed-background-color:
|
intermediate-pressed-background-color:
|
||||||
mix(map-get($t, medium-color), map-get($t, background-color), 2.6%),
|
mix(map-get($t, medium-color), map-get($t, background-color), 2.6%),
|
||||||
disabled-background-color: shade(map-get($t, background-color), 5%),
|
disabled-background-color: shade(map-get($t, background-color), 5%),
|
||||||
|
unselected-background-color:
|
||||||
|
mix(map-get($t, medium-color), map-get($t, background-color), 9%),
|
||||||
|
unselected-background-color-hover:
|
||||||
|
mix(map-get($t, medium-color), map-get($t, background-color), 14%),
|
||||||
action-background-color-focus: shade(map-get($t, action-color), 20%),
|
action-background-color-focus: shade(map-get($t, action-color), 20%),
|
||||||
action-background-color-focus-tr: rgba(shade(map-get($t, action-color), 20%), 0.1),
|
action-background-color-focus-tr: rgba(shade(map-get($t, action-color), 20%), 0.1),
|
||||||
error-background-color-focus: shade(map-get($t, error-color), 20%),
|
error-background-color-focus: shade(map-get($t, error-color), 20%),
|
||||||
|
|
|
@ -16,18 +16,25 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="select-entry__hint-text"><span class="shortcut">{{keyEnter}}</span>: {{res 'selectEntryEnterHint'}}</div>
|
<div class="select-entry__hint-text"><span class="shortcut">{{keyEnter}}</span>: {{res 'selectEntryEnterHint'}}</div>
|
||||||
<div class="select-entry__hint-text"><span class="shortcut">{{keyEsc}}</span>: {{res 'selectEntryEscHint'}}</div>
|
<div class="select-entry__hint-text"><span class="shortcut">{{keyEsc}}</span>: {{res 'selectEntryEscHint'}}</div>
|
||||||
|
<div class="select-entry__hint-text">{{res 'selectEntryTypingHint'}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{#if filterText}}
|
|
||||||
<div class="select-entry__header-filter" id="select-entry__header-filter">
|
|
||||||
<input type="text" readonly value="{{filterText}}" class="select-entry__header-filter-input" />
|
|
||||||
<i class="select-entry__header-filter-clear fa fa-times"></i>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="select-entry__message">
|
<div class="select-entry__message">
|
||||||
<div class="select-entry__message-text">{{topMessage}}</div>
|
<div class="select-entry__message-text">{{topMessage}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="select-entry__filters">
|
||||||
|
{{#each filters as |filter|}}
|
||||||
|
<div class="select-entry__filter {{#if filter.active}}select-entry__filter--active{{/if}}"
|
||||||
|
data-filter="{{filter.id}}"
|
||||||
|
data-active="{{filter.active}}"
|
||||||
|
>
|
||||||
|
<i class="fa {{#if filter.active}}fa-check-square-o{{else}}fa-square-o{{/if}} select-entry__filter-check"></i>
|
||||||
|
<i class="fa fa-filter select-entry__filter-icon"></i>
|
||||||
|
<div class="select-entry__filter-text">{{filter.type}}{{#if filter.text}}: {{/if}}{{filter.text}}</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
<div class="select-entry__items">
|
<div class="select-entry__items">
|
||||||
<div class="scroller">
|
<div class="scroller">
|
||||||
{{#if itemsHtml}}
|
{{#if itemsHtml}}
|
||||||
|
|
|
@ -8,6 +8,7 @@ Release notes
|
||||||
`+` better Touch ID error messages
|
`+` better Touch ID error messages
|
||||||
`-` legacy auto-type removed
|
`-` legacy auto-type removed
|
||||||
`+` displaying the reason why unlock is requested
|
`+` displaying the reason why unlock is requested
|
||||||
|
`+` filters on the auto-type entry selection screen
|
||||||
`+` adding multiple websites to one entry
|
`+` adding multiple websites to one entry
|
||||||
`-` fixed a crash after disabling USB devices on Linux
|
`-` fixed a crash after disabling USB devices on Linux
|
||||||
`+` tightened content security policy
|
`+` tightened content security policy
|
||||||
|
|
|
@ -41,4 +41,34 @@ describe('UrlFormat', () => {
|
||||||
})
|
})
|
||||||
).to.eql('hello=world&data=%3D%20%26');
|
).to.eql('hello=world&data=%3D%20%26');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should remove anchor for short urls', () => {
|
||||||
|
expect(
|
||||||
|
UrlFormat.presentAsShortUrl('https://example.com/path?query=1#anchor' + '0'.repeat(100))
|
||||||
|
).to.eql('https://example.com/path?query=1#…');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove query string for short urls', () => {
|
||||||
|
expect(
|
||||||
|
UrlFormat.presentAsShortUrl(
|
||||||
|
'https://example.com/path?query=' + '1'.repeat(100) + '#anchor' + '0'.repeat(100)
|
||||||
|
)
|
||||||
|
).to.eql('https://example.com/path?…');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove query parts of path for short urls', () => {
|
||||||
|
expect(
|
||||||
|
UrlFormat.presentAsShortUrl(
|
||||||
|
'https://example.com/path/' + '1'.repeat(100) + '/' + '0'.repeat(100)
|
||||||
|
)
|
||||||
|
).to.eql('https://example.com/path/…');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not remove domain for short urls', () => {
|
||||||
|
expect(
|
||||||
|
UrlFormat.presentAsShortUrl(
|
||||||
|
'https://example' + '0'.repeat(100) + '.com/' + '1'.repeat(100)
|
||||||
|
)
|
||||||
|
).to.eql('https://example' + '0'.repeat(100) + '.com/…');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue