fontawesome 5

This commit is contained in:
antelle 2020-11-25 18:20:53 +01:00
parent 8925a48822
commit 63b7b32e9c
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
62 changed files with 571 additions and 179 deletions

View File

@ -111,13 +111,6 @@ module.exports = function (grunt) {
expand: true,
nonull: true
},
fonts: {
src: 'node_modules/font-awesome/fonts/fontawesome-webfont.*',
dest: 'tmp/fonts/',
nonull: true,
expand: true,
flatten: true
},
'desktop-html': {
src: 'dist/index.html',
dest: 'tmp/desktop/app/index.html',

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M339 314.9L175.4 32h161.2l163.6 282.9H339zm-137.5 23.6L120.9 480h310.5L512 338.5H201.5zM154.1 67.4L0 338.5 80.6 480 237 208.8 154.1 67.4z"/></svg>

Before

Width:  |  Height:  |  Size: 217 B

View File

@ -1 +0,0 @@
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="256" height="256" version="1.1" viewBox="0 0 256 256"><g transform="translate(296.64282,-100.61434)"><g transform="translate(222.85714,-11.428576)"><g transform="matrix(0.83394139,0,0,0.83394139,-86.101383,10.950635)"><path d="m-419.5 365.94c-18.48-4.62-28.77-19.31-28.81-41.1-0.01-6.97 0.49-10.31 2.23-14.79 4.26-10.99 15.55-19.27 30.41-22.33 7.39-1.52 9.67-3.15 9.67-6.92 0-1.18 0.88-4.71 1.95-7.83 4.88-14.2 13.93-26.03 23.59-30.87 10.11-5.07 15.22-6.21 27.45-6.14 17.38 0.09 26.04 3.86 38.17 16.6l6.67 7 5.97-2.07c28.91-10.01 57.73 7.03 60.06 35.49l0.64 7.79 5.69 2.04c16.26 5.83 23.9 18.06 22.52 36.04-0.91 11.76-6.4 21.15-15.11 25.81l-4.09 2.19-91 0.18c-69.93 0.13-92.16-0.11-96-1.07zM-487.72 353.36" fill="#000"/><path d="m-487.72 353.36c-10.79-2.56-22.22-12.09-27.58-22.99-3.04-6.18-3.2-7.09-3.2-18.03 0-10.4 0.26-12.07 2.68-17.23 5.1-10.89 14.88-18.75 27.15-21.84 2.59-0.65 5.02-1.69 5.41-2.31 0.38-0.62 0.81-4 0.95-7.5 0.85-21.78 15.15-40.97 35.1-47.14 10.78-3.33 24.33-2.51 36.05 2.18 3.72 1.49 3.3 1.81 11.16-8.5 4.65-6.1 14.05-13.68 21.74-17.55 8.3-4.17 16.94-6.09 27.26-6.07 28.86 0.07 53.73 18.12 62.92 45.67 2.94 8.8 2.79 11.27-0.67 11.34-1.51 0.03-5.85 0.86-9.63 1.85l-6.88 1.79-6.28-6.28c-17.7-17.7-46.59-21.53-71.15-9.42-9.81 4.84-17.7 11.78-23.65 20.83-4.25 6.45-9.66 18.48-9.66 21.47 0 2.12-1.72 3.18-9.05 5.58-22.69 7.44-35.94 24.63-35.93 46.62 0 8 2.06 17.8 4.93 23.41 1.08 2.11 1.68 4.13 1.34 4.47-0.88 0.88-29.11 0.58-33.01-0.35z" /></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M465.69 311.917V200.083H363.175v111.834zm-69.897-18.639a4.66 4.66 0 01-4.659-4.659v-65.237a4.66 4.66 0 014.659-4.66h37.278a4.66 4.66 0 014.66 4.66v65.237a4.66 4.66 0 01-4.66 4.66h-37.278z"/><path d="M400.453 251.34v-23.299h27.959v23.299zm0 32.618v-23.299h27.959v23.299zM46.31 187.656v136.688c0 8.564 6.968 15.532 15.532 15.532h21.746V204.742a4.66 4.66 0 019.319 0v135.134h245.415c8.565 0 15.533-6.968 15.533-15.532V187.656c0-8.564-6.968-15.532-15.533-15.532H61.842c-8.565 0-15.532 6.968-15.532 15.532zm241.936 68.6c.122 9.637-7.529 17.293-17.166 17.416-9.359-.354-17.016-8.006-16.662-17.366-.122-9.636 7.529-17.293 16.889-16.938 9.637-.124 17.293 7.528 16.939 16.888zm-41.921-28.528a4.658 4.658 0 011.679 6.372c-3.865 6.631-5.909 14.266-5.909 22.082v.014c-.143 8.152 1.746 15.601 5.603 22.206a4.66 4.66 0 01-8.048 4.7c-4.73-8.099-7.057-17.196-6.873-26.984v-.021c0-9.381 2.48-18.637 7.176-26.69a4.657 4.657 0 016.372-1.679zm-23.7-17.48a4.659 4.659 0 011.395 6.441c-7.725 11.993-11.78 25.622-11.613 39.406-.164 14.287 3.794 28.031 11.327 39.791a4.66 4.66 0 01-7.849 5.027c-8.511-13.288-12.909-28.806-12.799-44.815-.13-15.503 4.387-30.927 13.099-44.455a4.66 4.66 0 016.44-1.395zm-22.433-16.741a4.656 4.656 0 011.272 6.466c-11.136 16.59-17.074 35.936-17.174 55.945-.244 20.163 5.497 39.619 16.606 56.34a4.66 4.66 0 01-7.762 5.158c-11.901-17.914-18.172-38.71-18.172-60.224 0-.452.003-.901.008-1.354.108-21.815 6.594-42.941 18.756-61.059a4.66 4.66 0 016.466-1.272z"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -150,7 +150,7 @@ const ChalRespCalculator = {
header: Locale.yubiKeyNoKeyHeader,
body: Locale.yubiKeyNoKeyBody.replace('{}', serial),
buttons: [Alerts.buttons.cancel],
iconSvg: 'usb-token',
icon: 'usb-token',
cancel: () => {
logger.info('No key alert closed');
@ -173,7 +173,7 @@ const ChalRespCalculator = {
header: Locale.yubiKeyTouchRequestedHeader,
body: Locale.yubiKeyTouchRequestedBody.replace('{}', serial),
buttons: [Alerts.buttons.cancel],
iconSvg: 'usb-token',
icon: 'usb-token',
cancel: () => {
logger.info('Touch alert closed');

View File

@ -3,10 +3,10 @@ const IconMap = [
'globe',
'exclamation-triangle',
'server',
'thumb-tack',
'thumbtack',
'comments-o',
'puzzle-piece',
'pencil-square-o',
'edit',
'plug',
'newspaper-o',
'paperclip',
@ -22,13 +22,13 @@ const IconMap = [
'cog',
'clipboard',
'paper-plane-o',
'television',
'tv',
'bolt',
'inbox',
'floppy-o',
'hdd-o',
'dot-circle-o',
'expeditedssl',
'save',
'hdd',
'dot-circle',
'user-lock',
'terminal',
'print',
'map-signs',
@ -38,11 +38,11 @@ const IconMap = [
'archive',
'credit-card',
'windows',
'clock-o',
'clock',
'search',
'flask',
'gamepad',
'trash-o',
'trash',
'sticky-note-o',
'ban',
'question-circle',
@ -53,19 +53,19 @@ const IconMap = [
'unlock-alt',
'lock',
'check',
'pencil',
'picture-o',
'pencil-alt',
'image',
'book',
'list-alt',
'user-secret',
'cutlery',
'utensils',
'home',
'star-o',
'star',
'linux',
'map-pin',
'apple',
'wikipedia-w',
'usd',
'dollar-sign',
'calendar',
'mobile'
];

View File

@ -6,6 +6,7 @@ const Links = {
BetaWebApp: 'https://beta.keeweb.info',
License: 'https://github.com/keeweb/keeweb/blob/master/LICENSE',
LicenseApache: 'https://opensource.org/licenses/Apache-2.0',
LicenseLinkCCBY40: 'https://creativecommons.org/licenses/by/4.0/',
UpdateDesktop: 'https://github.com/keeweb/keeweb/releases/download/v{ver}/UpdateDesktop.zip',
ReleaseNotes: 'https://github.com/keeweb/keeweb/blob/master/release-notes.md#release-notes',
SelfHostedDropbox: 'https://github.com/keeweb/keeweb#self-hosting',

View File

@ -4,4 +4,3 @@ import 'hbs-helpers/ifeq';
import 'hbs-helpers/ifneq';
import 'hbs-helpers/ifemptyoreq';
import 'hbs-helpers/res';
import 'hbs-helpers/svg';

View File

@ -1,9 +0,0 @@
import Handlebars from 'hbs';
Handlebars.registerHelper('svg', (name, cls) => {
const icon = require(`svg/${name}.svg`).default;
if (typeof cls === 'string') {
return `<svg class="${cls}"` + icon.substr(4);
}
return icon;
});

View File

@ -48,7 +48,7 @@ function getIcon(ext) {
case 'log':
case 'rtf':
case 'pem':
return 'file-text-o';
return 'file-alt-o';
case 'html':
case 'htm':
case 'js':

View File

@ -71,7 +71,7 @@ class YubiKeyOtpModel extends ExternalOtpDeviceModel {
id: this.entryId(code.title, code.user),
device: this,
deviceSubId: serial,
icon: 'clock-o',
icon: 'clock',
title: code.title,
user: code.user,
needsTouch: code.needsTouch

View File

@ -42,7 +42,7 @@ class MenuModel extends Model {
this.trashSection = new MenuSectionModel([
{
locTitle: 'menuTrash',
icon: 'trash',
icon: 'trash-alt',
shortcut: Keys.DOM_VK_D,
filterKey: 'trash',
filterValue: true,

View File

@ -11,7 +11,7 @@ class StorageGDrive extends StorageBase {
name = 'gdrive';
enabled = true;
uipos = 30;
iconSvg = 'google-drive';
icon = 'google-drive';
_baseUrl = 'https://www.googleapis.com/drive/v3';
_baseUrlUpload = 'https://www.googleapis.com/upload/drive/v3';

View File

@ -8,7 +8,7 @@ class StorageOneDrive extends StorageBase {
name = 'onedrive';
enabled = true;
uipos = 40;
iconSvg = 'onedrive';
icon = 'onedrive';
_baseUrl = 'https://graph.microsoft.com/v1.0/me';

View File

@ -15,7 +15,6 @@ const MaxRequestRetries = 3;
class StorageBase {
name = null;
icon = null;
iconSvg = null;
enabled = false;
system = false;
uipos = null;

View File

@ -241,7 +241,7 @@ class AutoTypeSelectView extends View {
if (entry.fields.otp) {
options.push({
value: '{TOTP}',
icon: 'clock-o',
icon: 'clock',
text: Locale.autoTypeSelectionOtp
});
}

View File

@ -236,7 +236,7 @@ class DetailsView extends View {
if (fieldView.isHidden()) {
moreOptions.push({
value: 'add:' + fieldView.model.name,
icon: 'pencil',
icon: 'pencil-alt',
text: Locale.detMenuAddField.replace('{}', fieldView.model.title)
});
}
@ -263,7 +263,7 @@ class DetailsView extends View {
text: Locale.detMenuHideEmpty
});
}
moreOptions.push({ value: 'otp', icon: 'clock-o', text: Locale.detSetupOtp });
moreOptions.push({ value: 'otp', icon: 'clock', text: Locale.detSetupOtp });
if (AutoType.enabled) {
moreOptions.push({
value: 'auto-type',
@ -457,7 +457,7 @@ class DetailsView extends View {
return;
}
this.model.initOtpGenerator();
this.model.initOtpGenerator?.();
if (this.model.external) {
return;
}
@ -824,7 +824,7 @@ class DetailsView extends View {
Alerts.yesno({
header: Locale.detDelToTrash,
body: Locale.detDelToTrashBody,
icon: 'trash',
icon: 'trash-alt',
success: doMove
});
} else {
@ -865,19 +865,19 @@ class DetailsView extends View {
if (this.model.external) {
options.push({
value: 'det-copy-otp',
icon: 'clipboard',
icon: 'copy',
text: Locale.detMenuCopyOtp
});
} else {
options.push({
value: 'det-copy-password',
icon: 'clipboard',
icon: 'copy',
text: Locale.detMenuCopyPassword
});
}
options.push({
value: 'det-copy-user',
icon: 'clipboard',
icon: 'copy',
text: Locale.detMenuCopyUser
});
}
@ -887,7 +887,7 @@ class DetailsView extends View {
if (canCopy) {
options.push({
value: 'copy-to-clipboard',
icon: 'copy',
icon: 'clipboard',
text: Locale.detCopyEntryToClipboard
});
}

View File

@ -321,9 +321,9 @@ class FieldView extends View {
const actions = [];
if (this.value) {
actions.push({ name: 'copy', icon: 'clipboard' });
actions.push({ name: 'copy', icon: 'copy' });
}
actions.push({ name: 'edit', icon: 'pencil' });
actions.push({ name: 'edit', icon: 'pencil-alt' });
if (this.value instanceof kdbxweb.ProtectedValue) {
actions.push({ name: 'reveal', icon: 'eye' });
}

View File

@ -51,7 +51,7 @@ class IconSelectView extends View {
return;
}
this.downloadingFavicon = true;
this.$el.find('.icon-select__icon-download>i').addClass('fa-spinner fa-spin');
this.$el.find('.icon-select__icon-download>i').addClass('fa-spinner spin');
this.$el
.find('.icon-select__icon-download')
.removeClass('icon-select__icon--download-error');
@ -62,7 +62,7 @@ class IconSelectView extends View {
img.onload = () => {
this.setSpecialImage(img, 'download');
this.$el.find('.icon-select__icon-download img').remove();
this.$el.find('.icon-select__icon-download>i').removeClass('fa-spinner fa-spin');
this.$el.find('.icon-select__icon-download>i').removeClass('fa-spinner spin');
this.$el
.find('.icon-select__icon-download')
.addClass('icon-select__icon--custom-selected')
@ -71,7 +71,7 @@ class IconSelectView extends View {
};
img.onerror = (e) => {
logger.error('Favicon download error: ' + url, e);
this.$el.find('.icon-select__icon-download>i').removeClass('fa-spinner fa-spin');
this.$el.find('.icon-select__icon-download>i').removeClass('fa-spinner spin');
this.$el
.find('.icon-select__icon-download')
.removeClass('icon-select__icon--custom-selected')

View File

@ -39,64 +39,64 @@ class ListSearchView extends View {
this.sortOptions = [
{
value: 'title',
icon: 'sort-alpha-asc',
icon: 'sort-alpha-down',
loc: () =>
StringFormat.capFirst(Locale.title) + ' ' + this.addArrow(Locale.searchAZ)
},
{
value: '-title',
icon: 'sort-alpha-desc',
icon: 'sort-alpha-down-alt',
loc: () =>
StringFormat.capFirst(Locale.title) + ' ' + this.addArrow(Locale.searchZA)
},
{
value: 'website',
icon: 'sort-alpha-asc',
icon: 'sort-alpha-down',
loc: () =>
StringFormat.capFirst(Locale.website) + ' ' + this.addArrow(Locale.searchAZ)
},
{
value: '-website',
icon: 'sort-alpha-desc',
icon: 'sort-alpha-down-alt',
loc: () =>
StringFormat.capFirst(Locale.website) + ' ' + this.addArrow(Locale.searchZA)
},
{
value: 'user',
icon: 'sort-alpha-asc',
icon: 'sort-alpha-down',
loc: () => StringFormat.capFirst(Locale.user) + ' ' + this.addArrow(Locale.searchAZ)
},
{
value: '-user',
icon: 'sort-alpha-desc',
icon: 'sort-alpha-down-alt',
loc: () => StringFormat.capFirst(Locale.user) + ' ' + this.addArrow(Locale.searchZA)
},
{
value: 'created',
icon: 'sort-numeric-asc',
icon: 'sort-numeric-down',
loc: () => Locale.searchCreated + ' ' + this.addArrow(Locale.searchON)
},
{
value: '-created',
icon: 'sort-numeric-desc',
icon: 'sort-numeric-down-alt',
loc: () => Locale.searchCreated + ' ' + this.addArrow(Locale.searchNO)
},
{
value: 'updated',
icon: 'sort-numeric-asc',
icon: 'sort-numeric-down',
loc: () => Locale.searchUpdated + ' ' + this.addArrow(Locale.searchON)
},
{
value: '-updated',
icon: 'sort-numeric-desc',
icon: 'sort-numeric-down-alt',
loc: () => Locale.searchUpdated + ' ' + this.addArrow(Locale.searchNO)
},
{
value: '-attachments',
icon: 'sort-amount-desc',
icon: 'sort-amount-down',
loc: () => Locale.searchAttachments
},
{ value: '-rank', icon: 'sort-amount-desc', loc: () => Locale.searchRank }
{ value: '-rank', icon: 'sort-amount-down', loc: () => Locale.searchRank }
];
this.sortIcons = {};
this.sortOptions.forEach((opt) => {

View File

@ -162,20 +162,16 @@ class OpenView extends View {
getLastOpenFiles() {
return this.model.fileInfos.map((fileInfo) => {
let icon = 'file-text';
let icon = 'file-alt';
const storage = Storage[fileInfo.storage];
if (storage && storage.icon) {
icon = storage.icon;
}
if (storage && storage.iconSvg) {
icon = null;
}
return {
id: fileInfo.id,
name: fileInfo.name,
path: this.getDisplayedPath(fileInfo),
icon,
iconSvg: storage ? storage.iconSvg : undefined
icon
};
});
}
@ -807,7 +803,7 @@ class OpenView extends View {
Alerts.alert({
header: Locale.openSelectFile,
body: Locale.openSelectFileBody,
icon: storage.icon || 'files-o',
icon: storage.icon || 'file-alt-o',
buttons: [{ result: '', title: Locale.alertCancel }],
esc: '',
click: '',
@ -1064,7 +1060,7 @@ class OpenView extends View {
Alerts.alert({
header: Locale.openChalRespHeader,
iconSvg: 'usb-token',
icon: 'usb-token',
buttons: [{ result: '', title: Locale.alertCancel }],
esc: '',
click: '',

View File

@ -12,6 +12,7 @@ class SettingsAboutView extends View {
version: RuntimeInfo.version,
licenseLink: Links.License,
licenseLinkApache: Links.LicenseApache,
licenseLinkCCBY40: Links.LicenseLinkCCBY40,
repoLink: Links.Repo,
donationLink: Links.Donation,
isDesktop: Features.isDesktop

View File

@ -85,7 +85,6 @@ class SettingsFileView extends View {
storageProviders.push({
name: prv.name,
icon: prv.icon,
iconSvg: prv.iconSvg,
own: name === fileStorage,
backup: prv.backup
});
@ -337,7 +336,7 @@ class SettingsFileView extends View {
Alerts.alert({
header: '',
body: '',
icon: storage.icon || 'files-o',
icon: storage.icon || 'file-alt-o',
buttons: [Alerts.buttons.ok, Alerts.buttons.cancel],
esc: '',
opaque: true,

View File

@ -327,7 +327,7 @@
}
&:before {
@include position(absolute, 0 0 null null);
@include fa-icon();
@include fa-icon;
cursor: pointer;
padding: 0.3em $base-padding-h;
}

View File

@ -36,8 +36,7 @@
outline: focused-outline();
}
}
&-i,
&-svg {
&-i {
font-size: 4em;
}
&-text {
@ -46,15 +45,8 @@
color: var(--medium-color);
}
}
&-svg {
line-height: 0;
> svg {
@include size(1em);
}
}
@include mobile() {
&-i,
&-svg {
&-i {
font-size: 4.6em;
}
&-text {
@ -62,8 +54,7 @@
}
.open__icons--lower & {
margin: 14px;
&-i,
&-svg {
&-i {
font-size: 4.2em;
margin-bottom: 0.1em;
}
@ -105,6 +96,8 @@
right: 0;
}
color: var(--muted-color);
line-height: 3em;
height: 3em;
> i {
font-size: 3em;
@include mobile {
@ -304,13 +297,8 @@
}
&-icon {
width: 2em;
&--svg > svg {
vertical-align: middle;
@include size(1em);
path {
fill: var(--muted-color);
}
}
position: relative;
top: 0.1em;
}
&-text {
flex-grow: 1;

View File

@ -142,16 +142,12 @@
display: inline-block;
margin-right: $base-padding-h;
text-align: center;
> i,
> svg {
> i {
display: block;
font-size: 3em;
padding: $base-padding-px;
margin: auto;
}
> svg {
@include size(1em);
}
&:hover {
transition: color $base-duration $base-timing;
color: var(--medium-color);

View File

@ -7,6 +7,7 @@
@import 'colors';
@import 'variables';
@import 'media';
@import 'icon-font';
@import 'body';
@import 'grid-settings';
@import 'buttons';

View File

@ -85,13 +85,3 @@
}
}
}
.svg-btn {
svg path {
transition: fill $base-duration $base-timing;
fill: var(--text-color);
}
&:hover svg path {
fill: var(--medium-color);
}
}

View File

@ -0,0 +1,181 @@
@font-face {
font-family: 'Font Awesome 5 Free';
font-style: normal;
font-weight: 400;
src: url('fontawesome.woff2') format('woff2');
}
@mixin fa-icon {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
font-style: normal;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
display: inline-block;
}
.fa {
@include fa-icon;
}
$fa-glyph-counter: 61440; // 0xf000
@function next-fa-glyph() {
$fa-glyph-counter: $fa-glyph-counter + 1 !global;
$lo-part: $fa-glyph-counter % 256;
$hi-part: ($fa-glyph-counter - $lo-part) / 256;
$hex-num-str: str-slice(#{rgb($hi-part, $lo-part, 1)}, 2, 5);
$glyph: unquote('"\\#{$hex-num-str}"');
@return $glyph;
}
// icons listed below will be automatically added to the generated icon font, see build/loaders/fontawesome-loader.js
// if the icon has "-o" suffix, it will be used from the "regular" font, otherwise from "solid" or "brands"
// -o is used because it's similar to an empty bullet and this used to be a convention in fontawesome 4
$fa-var-square: next-fa-glyph();
$fa-var-square-o: next-fa-glyph();
$fa-var-check-square-o: next-fa-glyph();
$fa-var-bookmark: next-fa-glyph();
$fa-var-bookmark-o: next-fa-glyph();
$fa-var-eye: next-fa-glyph();
$fa-var-eye-slash: next-fa-glyph();
$fa-var-bolt: next-fa-glyph();
$fa-var-unlock: next-fa-glyph();
$fa-var-lock: next-fa-glyph();
$fa-var-check: next-fa-glyph();
$fa-var-times: next-fa-glyph();
$fa-var-folder: next-fa-glyph();
$fa-var-folder-open: next-fa-glyph();
$fa-var-ban: next-fa-glyph();
$fa-var-dropbox: next-fa-glyph();
$fa-var-google-drive: next-fa-glyph();
$fa-var-plus: next-fa-glyph();
$fa-var-ellipsis-h: next-fa-glyph();
$fa-var-ellipsis-v: next-fa-glyph();
$fa-var-magic: next-fa-glyph();
$fa-var-cog: next-fa-glyph();
$fa-var-server: next-fa-glyph();
$fa-var-file-alt: next-fa-glyph();
$fa-var-file-alt-o: next-fa-glyph();
$fa-var-file-code-o: next-fa-glyph();
$fa-var-file-pdf-o: next-fa-glyph();
$fa-var-file-archive-o: next-fa-glyph();
$fa-var-file-word-o: next-fa-glyph();
$fa-var-file-excel-o: next-fa-glyph();
$fa-var-file-powerpoint-o: next-fa-glyph();
$fa-var-file-image-o: next-fa-glyph();
$fa-var-file-video-o: next-fa-glyph();
$fa-var-file-audio-o: next-fa-glyph();
$fa-var-onedrive: next-fa-glyph();
$fa-var-question: next-fa-glyph();
$fa-var-sign-out-alt: next-fa-glyph();
$fa-var-sync-alt: next-fa-glyph();
$fa-var-level-down-alt: next-fa-glyph();
$fa-var-tag: next-fa-glyph();
$fa-var-tags: next-fa-glyph();
$fa-var-th-large: next-fa-glyph();
$fa-var-trash: next-fa-glyph();
$fa-var-trash-alt: next-fa-glyph();
$fa-var-keyboard-o: next-fa-glyph();
$fa-var-puzzle-piece: next-fa-glyph();
$fa-var-usb: next-fa-glyph();
$fa-var-info: next-fa-glyph();
$fa-var-info-circle: next-fa-glyph();
$fa-var-key: next-fa-glyph();
$fa-var-globe: next-fa-glyph();
$fa-var-exclamation-triangle: next-fa-glyph();
$fa-var-thumbtack: next-fa-glyph();
$fa-var-comments-o: next-fa-glyph();
$fa-var-edit: next-fa-glyph();
$fa-var-plug: next-fa-glyph();
$fa-var-newspaper-o: next-fa-glyph();
$fa-var-paperclip: next-fa-glyph();
$fa-var-camera: next-fa-glyph();
$fa-var-wifi: next-fa-glyph();
$fa-var-link: next-fa-glyph();
$fa-var-battery-three-quarters: next-fa-glyph();
$fa-var-bars: next-fa-glyph();
$fa-var-barcode: next-fa-glyph();
$fa-var-certificate: next-fa-glyph();
$fa-var-bullseye: next-fa-glyph();
$fa-var-desktop: next-fa-glyph();
$fa-var-envelope-o: next-fa-glyph();
$fa-var-clipboard: next-fa-glyph();
$fa-var-paper-plane-o: next-fa-glyph();
$fa-var-tv: next-fa-glyph();
$fa-var-inbox: next-fa-glyph();
$fa-var-save: next-fa-glyph();
$fa-var-hdd: next-fa-glyph();
$fa-var-dot-circle: next-fa-glyph();
$fa-var-user-lock: next-fa-glyph();
$fa-var-terminal: next-fa-glyph();
$fa-var-print: next-fa-glyph();
$fa-var-map-signs: next-fa-glyph();
$fa-var-flag-checkered: next-fa-glyph();
$fa-var-wrench: next-fa-glyph();
$fa-var-laptop: next-fa-glyph();
$fa-var-archive: next-fa-glyph();
$fa-var-credit-card: next-fa-glyph();
$fa-var-windows: next-fa-glyph();
$fa-var-clock: next-fa-glyph();
$fa-var-search: next-fa-glyph();
$fa-var-flask: next-fa-glyph();
$fa-var-gamepad: next-fa-glyph();
$fa-var-sticky-note-o: next-fa-glyph();
$fa-var-question-circle: next-fa-glyph();
$fa-var-cube: next-fa-glyph();
$fa-var-folder-o: next-fa-glyph();
$fa-var-folder-open-o: next-fa-glyph();
$fa-var-database: next-fa-glyph();
$fa-var-unlock-alt: next-fa-glyph();
$fa-var-pencil-alt: next-fa-glyph();
$fa-var-image: next-fa-glyph();
$fa-var-book: next-fa-glyph();
$fa-var-list-alt: next-fa-glyph();
$fa-var-user-secret: next-fa-glyph();
$fa-var-utensils: next-fa-glyph();
$fa-var-home: next-fa-glyph();
$fa-var-star: next-fa-glyph();
$fa-var-linux: next-fa-glyph();
$fa-var-map-pin: next-fa-glyph();
$fa-var-apple: next-fa-glyph();
$fa-var-wikipedia-w: next-fa-glyph();
$fa-var-dollar-sign: next-fa-glyph();
$fa-var-calendar: next-fa-glyph();
$fa-var-mobile: next-fa-glyph();
$fa-var-spinner: next-fa-glyph();
$fa-var-minus-circle: next-fa-glyph();
$fa-var-keeweb: next-fa-glyph();
$fa-var-copy: next-fa-glyph();
$fa-var-clone: next-fa-glyph();
$fa-var-chevron-down: next-fa-glyph();
$fa-var-chevron-left: next-fa-glyph();
$fa-var-qrcode: next-fa-glyph();
$fa-var-sort-alpha-down: next-fa-glyph();
$fa-var-sort-alpha-down-alt: next-fa-glyph();
$fa-var-sort-numeric-down: next-fa-glyph();
$fa-var-sort-numeric-down-alt: next-fa-glyph();
$fa-var-sort-amount-down: next-fa-glyph();
$fa-var-language: next-fa-glyph();
$fa-var-circle: next-fa-glyph();
$fa-var-circle-o: next-fa-glyph();
$fa-var-arrow-circle-left: next-fa-glyph();
$fa-var-cloud-download-alt: next-fa-glyph();
$fa-var-caret-down: next-fa-glyph();
$fa-var-long-arrow-alt-left: next-fa-glyph();
$fa-var-long-arrow-alt-right: next-fa-glyph();
$fa-var-github-alt: next-fa-glyph();
$fa-var-code: next-fa-glyph();
$fa-var-html5: next-fa-glyph();
$fa-var-chrome: next-fa-glyph();
$fa-var-firefox-browser: next-fa-glyph();
$fa-var-safari: next-fa-glyph();
$fa-var-opera: next-fa-glyph();
$fa-var-edge: next-fa-glyph();
$fa-var-twitter: next-fa-glyph();
$fa-var-paint-brush: next-fa-glyph();
$fa-var-at: next-fa-glyph();

View File

@ -25,6 +25,24 @@
animation: shake 50s cubic-bezier(0.36, 0.07, 0.19, 0.97) 0s;
}
.rotate-90,
.fa.rotate-90:before {
transform: rotate(90deg);
}
.spin {
animation: spin 2s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes flip3d {
from {
transform: rotateY(0);

View File

@ -30,11 +30,6 @@
&__icon {
font-size: $modal-icon-size;
text-align: center;
&--svg {
fill: var(--text-color);
width: 1.4em;
align-self: center;
}
}
&__header {
user-select: text;

View File

@ -1,7 +1,6 @@
$fa-font-path: '~font-awesome/fonts';
@import '~normalize.css/normalize';
@import '~font-awesome/scss/font-awesome';
@import '~pikaday/scss/pikaday';
@import '~bourbon';

View File

@ -1,6 +1,6 @@
<div class="details__attachment-preview">
<div class="details__subview-close">
<i class="fa fa-chevron-left details__subview-close-pre"></i>{{res 'detHistoryReturn'}} <i class="fa fa-external-link-square details__subview-close-post"></i>
<i class="fa fa-chevron-left details__subview-close-pre"></i>{{res 'detHistoryReturn'}} <i class="fa fa-arrow-circle-left details__subview-close-post"></i>
</div>
<div class="details__attachment-preview-data"></div>
<i class="fa details__attachment-preview-icon"></i>

View File

@ -1,13 +1,13 @@
<div class="details__history">
<div class="details__subview-close">
<i class="fa fa-chevron-left details__subview-close-pre"></i>{{res 'detHistoryReturn'}} <i class="fa fa-external-link-square details__subview-close-post"></i>
<i class="fa fa-chevron-left details__subview-close-pre"></i>{{res 'detHistoryReturn'}} <i class="fa fa-arrow-circle-left details__subview-close-post"></i>
</div>
<div class="details__history-desc muted-color">{{res 'detHistoryClickPoint'}}</div>
<div class="details__history-top">
<div class="details__history-timeline">
<div class="details__history-timeline-axis"></div>
<div class="details__history-arrow-prev"><i class="fa fa-long-arrow-left"></i></div>
<div class="details__history-arrow-next"><i class="fa fa-long-arrow-right"></i></div>
<div class="details__history-arrow-prev"><i class="fa fa-long-arrow-alt-left"></i></div>
<div class="details__history-arrow-next"><i class="fa fa-long-arrow-alt-right"></i></div>
</div>
</div>
<div class="details__history-body">

View File

@ -47,7 +47,7 @@
{{#if deleted~}}
<i class="details__buttons-trash-del fa fa-minus-circle" title="{{res 'detDelEntryPerm'}}" tip-placement="top"></i>
{{~else~}}
<i class="details__buttons-trash fa fa-trash-o" title="{{res 'detDelEntry'}}" tip-placement="top"></i>
<i class="details__buttons-trash fa fa-trash-alt" title="{{res 'detDelEntry'}}" tip-placement="top"></i>
{{~/if~}}
<div class="details__attachments">
<input type="file" class="details__attachment-input-file hide-by-pos" multiple />

View File

@ -4,9 +4,9 @@
data-file-id="{{file.id}}" id="footer__db--{{file.id}}">
<i class="fa fa-{{#if file.active}}unlock{{else}}lock{{/if}}"></i> {{file.name}}
{{#if file.syncing~}}
<i class="fa fa-refresh fa-spin footer__db-sign"></i>
<i class="fa fa-sync-alt spin footer__db-sign"></i>
{{~else if file.syncError~}}
<i class="fa {{#if file.modified}}fa-circle{{else}}fa-circle-thin{{/if}} footer__db-sign footer__db-sign--error"
<i class="fa {{#if file.modified}}fa-circle{{else}}fa-circle-o{{/if}} footer__db-sign footer__db-sign--error"
title="{{res 'footerSyncError'}}: {{file.syncError}}"></i>
{{~else if file.modified~}}
<i class="fa fa-circle footer__db-sign"></i>
@ -25,5 +25,5 @@
{{/if}}
</div>
<div class="footer__btn footer__btn-generate" title="{{res 'footerTitleGen'}}" tip-placement="top" id="footer__btn-generate"><i class="fa fa-bolt"></i></div>
<div class="footer__btn footer__btn-lock" title="{{res 'footerTitleLock'}}" tip-placement="top-left" id="footer__btn-lock"><i class="fa fa-sign-out"></i></div>
<div class="footer__btn footer__btn-lock" title="{{res 'footerTitleLock'}}" tip-placement="top-left" id="footer__btn-lock"><i class="fa fa-sign-out-alt"></i></div>
</div>

View File

@ -1,6 +1,6 @@
<div class="gen-ps">
<div class="back-button">
{{res 'retToApp'}} <i class="fa fa-external-link-square"></i>
{{res 'retToApp'}} <i class="fa fa-arrow-circle-left"></i>
</div>
<div class="scroller">
<div class="gen-ps__content">

View File

@ -1,6 +1,6 @@
<div class="gen">
<div>{{res 'genLen'}}: <span class="gen__length-range-val">{{opt.length}}</span>
<i class="fa fa-refresh gen__btn-refresh gen__top-btn" title="{{res 'genNewPass'}}"></i>
<i class="fa fa-sync-alt gen__btn-refresh gen__top-btn" title="{{res 'genNewPass'}}"></i>
{{#unless showToggleButton}}
<input type="checkbox" id="gen__check-hide" class="gen__check-hide" {{#if hide}}checked{{/if}}>
<label for="gen__check-hide" class="fa gen__top-btn gen__check-hide-label"

View File

@ -1,6 +1,6 @@
<div class="grp">
<div class="back-button">
{{res 'retToApp'}} <i class="fa fa-external-link-square"></i>
{{res 'retToApp'}} <i class="fa fa-arrow-circle-left"></i>
</div>
<div class="scroller">
<div class="grp__content">
@ -43,7 +43,7 @@
<div class="scroller__bar-wrapper"><div class="scroller__bar"></div></div>
{{#unless readonly}}
<div class="grp__buttons">
<i class="grp__buttons-trash fa fa-trash-o" title="{{res 'grpTrash'}}" tip-placement="right"></i>
<i class="grp__buttons-trash fa fa-trash-alt" title="{{res 'grpTrash'}}" tip-placement="right"></i>
</div>
{{/unless}}
</div>

View File

@ -9,7 +9,7 @@
{{#if canDownloadFavicon}}
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-download"
data-val="special" data-special="download" title="{{res 'iconFavTitle'}}">
<i class="fa fa-cloud-download"></i>
<i class="fa fa-cloud-download-alt"></i>
</span>
{{/if}}
<span class="icon-select__icon icon-select__icon-btn icon-select__icon-select"

View File

@ -1,7 +1,7 @@
<div class="import-csv">
<div class="import-csv__top">
<div class="back-button">
{{res 'retToApp'}} <i class="fa fa-external-link-square"></i>
{{res 'retToApp'}} <i class="fa fa-arrow-circle-left"></i>
</div>
<h1>{{res 'importCsvTitle'}}</h1>
</div>

View File

@ -1,5 +1,5 @@
<div class="empty-block muted-color">
<div class="empty-block__icon"><i class="fa fa-key"></i></div>
<div class="empty-block__icon"><i class="fa fa-keeweb"></i></div>
<h1 class="empty-block__title">{{res 'listEmptyTitle'}}</h1>
<p class="empty-block__text">
{{#res 'listEmptyAdd'}} <i class="fa fa-plus"></i>{{/res}}

View File

@ -14,7 +14,7 @@
<i class="fa fa-plus"></i>
</div>
<div class="list__search-btn-sort" title="{{res 'searchSort'}}">
<i class="fa fa-sort-alpha-asc"></i>
<i class="fa fa-sort-alpha-down"></i>
</div>
<div class="list__search-adv {{#unless advEnabled}}hide{{/unless}}">
<div class="list__search-adv-text">{{res 'searchSearchIn'}}:</div>

View File

@ -2,8 +2,6 @@
<div class="modal__content">
{{#if icon}}
<i class="modal__icon fa fa-{{icon}}"></i>
{{else if iconSvg}}
{{{svg iconSvg 'modal__icon modal__icon--svg'}}}
{{/if}}
<div class="modal__header">{{header}}</div>
<div class="modal__body">

View File

@ -2,7 +2,7 @@
{{#if loading}}
<div class="open-chal-resp__head">
<p>
<i class="open-chal-resp__icon fa fa-spinner fa-spin"></i> {{res 'openChalRespLoading'}}
<i class="open-chal-resp__icon fa fa-spinner spin"></i> {{res 'openChalRespLoading'}}
</p>
</div>
{{else if error}}

View File

@ -19,7 +19,7 @@
<button class="btn-silent open__config-btn-cancel">{{res 'alertCancel'}}</button>
<button class="open__config-btn-ok">
<span class="open__config-btn-ok-text">{{res 'alertOk'}}</span>
<i class="open__config-btn-ok-spinner fa fa-spinner fa-spin"></i>
<i class="open__config-btn-ok-spinner fa fa-spinner spin"></i>
</button>
</div>
{{/if}}

View File

@ -13,9 +13,9 @@
<div class="open__icon-text">{{res 'openNew'}}</div>
</div>
{{/if}}
<div class="open__icon open__icon-yubikey svg-btn {{#unless canOpenYubiKey}}hide{{/unless}}"
<div class="open__icon open__icon-yubikey {{#unless canOpenYubiKey}}hide{{/unless}}"
tabindex="3" id="open__icon-yubikey">
<div class="open__icon-svg">{{{svg 'usb-token'}}}</div>
<i class="fa fa-usb-token open__icon-i"></i>
<div class="open__icon-text">YubiKey</div>
</div>
{{#if canOpenDemo}}
@ -34,17 +34,16 @@
{{/if}}
{{#if showLogo}}
<div class="open__icon open__icon-more id=open__icon-more">
<i class="fa fa-key open__icon-i"></i>
<i class="fa fa-keeweb open__icon-i"></i>
<div class="open__icon-text">KeeWeb</div>
</div>
{{/if}}
</div>
<div class="open__icons open__icons--lower hide">
{{#each storageProviders as |prv|}}
<div class="open__icon open__icon-storage svg-btn" data-storage="{{prv.name}}" tabindex="{{add @index 6}}"
<div class="open__icon open__icon-storage" data-storage="{{prv.name}}" tabindex="{{add @index 6}}"
id="open__icon-storage--{{prv.name}}">
{{#if prv.icon}}<i class="fa fa-{{prv.icon}} open__icon-i"></i>{{/if}}
{{#if prv.iconSvg}}<div class="open__icon-svg">{{{svg prv.iconSvg}}}</div>{{/if}}
<div class="open__icon-text">{{res prv.name}}</div>
</div>
{{/each}}
@ -81,8 +80,8 @@
<div class="open__pass-field-wrap">
<input class="open__pass-input" name="password" type="password" size="30" autocomplete="new-password" maxlength="1024"
placeholder="{{#if canOpen}}{{res 'openClickToOpen'}}{{/if}}" readonly tabindex="23" />
<div class="open__pass-enter-btn" tabindex="24"><i class="fa fa-level-down fa-rotate-90"></i></div>
<div class="open__pass-opening-icon"><i class="fa fa-spinner fa-spin"></i></div>
<div class="open__pass-enter-btn" tabindex="24"><i class="fa fa-level-down-alt rotate-90"></i></div>
<div class="open__pass-opening-icon"><i class="fa fa-spinner spin"></i></div>
</div>
<div class="open__settings">
<div class="open__settings-key-file hide" tabindex="25">
@ -92,7 +91,7 @@
</div>
<div class="open__settings-yubikey {{#if canUseChalRespYubiKey}}open__settings-yubikey--present{{/if}} hide"
tabindex="26" title="YubiKey">
<div class="open__settings-yubikey__text">YK</div> {{{svg 'usb-token' 'open__settings-yubikey-img'}}}
<div class="open__settings-yubikey__text">YK</div> <i class="fa fa-usb-token open__settings-yubikey-img"></i>{
</div>
</div>
<div class="open__last">
@ -100,7 +99,6 @@
<div class="open__last-item" data-id="{{file.id}}" title="{{file.path}}" tabindex="{{add @index 30}}"
id="open__last-item--{{file.id}}">
{{#if file.icon}}<i class="fa fa-{{file.icon}} open__last-item-icon"></i>{{/if}}
{{#if file.iconSvg}}<div class="open__last-item-icon open__last-item-icon--svg">{{{svg file.iconSvg}}}</div>{{/if}}
<span class="open__last-item-text">{{file.name}}</span>
{{#if ../canRemoveLatest}}<i class="fa fa-times open__last-item-icon-del"></i>{{/if}}
</div>

View File

@ -15,7 +15,8 @@
<li><a href="https://lodash.com/" target="_blank">lodash</a><span class="muted-color">, a modern JavaScript utility library delivering modularity, performance & extras</span></li>
<li><a href="https://jquery.com/" target="_blank">jQuery</a><span class="muted-color">, fast, small, and feature-rich JavaScript library</span></li>
<li><a href="https://marked.js.org/" target="_blank">marked</a><span class="muted-color">, a markdown parser and compiler</span></li>
<li><a href="https://github.com/cure53/DOMPurify" target="_blank">dompurify</a><span class="muted-color">, a DOM-only, super-fast, uber-tolerant XSS sanitizer</span></li>
<li><a href="https://github.com/cure53/DOMPurify" target="_blank">dompurify</a><span class="muted-color">, a DOM-only, super-fast, uber-tolerant XSS sanitizer, </span>
<a href="{{licenseLinkApache}}" class="muted-color" target="_blank">Apache-2.0 license</a></li>
<li><a href="https://github.com/TomFrost/node-phonetic" target="_blank">node-phonetic</a><span class="muted-color">, generates unique, pronounceable names</span></li>
</ul>
@ -30,7 +31,7 @@
<h3>UI components</h3>
<ul>
<li><a href="https://github.com/Diokuz/baron" target="_blank">baron</a><span class="muted-color">, native scroll with custom scrollbar</span></li>
<li><a href="https://dbushell.github.io/Pikaday/" target="_blank">pikaday</a><span class="muted-color">, a refreshing JavaScript datepicker</span></li>
<li><a href="https://github.com/Pikaday/Pikaday" target="_blank">pikaday</a><span class="muted-color">, a refreshing JavaScript datepicker</span></li>
</ul>
<h3>Desktop modules</h3>
@ -51,7 +52,7 @@
<h3>Styles</h3>
<ul>
<li><a href="https://sass-lang.com/" target="_blank">sass</a><span class="muted-color">, syntactically awesome stylesheets</span></li>
<li><a href="https://bourbon.io/" target="_blank">bourbon</a><span class="muted-color">, a simple and lightweight mixin library for Sass</span></li>
<li><a href="https://bourbon.io/" target="_blank">bourbon</a><span class="muted-color">, a lightweight Sass tool set</span></li>
<li><a href="https://github.com/thoughtbot/bitters" target="_blank">bitters</a><span class="muted-color">, styles, variables and structure for
Bourbon projects</span></li>
<li><a href="https://necolas.github.io/normalize.css/" target="_blank">normalize.css</a><span class="muted-color">, a modern, HTML5-ready alternative
@ -60,8 +61,8 @@
<h3>Graphics</h3>
<ul>
<li><a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">fontawesome</a><span class="muted-color">, the iconic font
and CSS toolkit</span></li>
<li><a href="https://fontawesome.com/" target="_blank">fontawesome</a><span class="muted-color">, the iconic SVG, font, and CSS toolkit, </span>
<a href="{{licenseLinkApache}}" class="muted-color" target="_blank">CC BY 4.0 License</a></li>
</ul>
<h2>{{res 'setAboutLic'}}</h2>

View File

@ -31,9 +31,8 @@
{{/ifneq}}
{{#each storageProviders as |prv|}}
{{#unless prv.own}}
<div class="settings__file-save-to settings__file-save-to-storage svg-btn" data-storage="{{prv.name}}">
<div class="settings__file-save-to settings__file-save-to-storage" data-storage="{{prv.name}}">
{{#if prv.icon}}<i class="fa fa-{{prv.icon}}"></i>{{/if}}
{{#if prv.iconSvg}}{{{svg prv.iconSvg}}}{{/if}}
<span>{{res prv.name}}</span>
</div>
{{/unless}}
@ -59,7 +58,7 @@
<h2>{{res 'settings'}}</h2>
<label for="settings__file-master-pass" class="settings__file-master-pass-label input-base">{{res 'setFilePass'}}:
<span class="settings__file-master-pass-warning">
<i class="fa fa-warning"></i> <span id="settings__file-master-pass-warning-text">{{res 'setFilePassChange'}}</span>
<i class="fa fa-exclamation-triangle"></i> <span id="settings__file-master-pass-warning-text">{{res 'setFilePassChange'}}</span>
</span>
</label>
<div class="hide">
@ -71,7 +70,7 @@
<div id="settings__file-confirm-master-pass-group">
<label for="settings__file-confirm-master-pass" class="settings__file-master-pass-label input-base">{{res 'setFileConfirmPass'}}:
<span class="settings__file-confirm-master-pass-warning">
<i class="fa fa-warning"></i> {{res 'setFilePassNotMatch'}}
<i class="fa fa-exclamation-triangle"></i> {{res 'setFilePassNotMatch'}}
</span>
</label>
<input type="password" class="settings__input input-base" id="settings__file-confirm-master-pass" autocomplete="confirm-password" />

View File

@ -18,9 +18,9 @@
</li>
<li>
<i class="fa fa-chrome"></i>
<i class="fa fa-firefox"></i>
<i class="fa fa-firefox-browser"></i>
<i class="fa fa-opera"></i>
<i class="fa fa-compass"></i>
<i class="fa fa-safari"></i>
<i class="fa fa-edge"></i>
<a href="{{webAppLink}}" target="_blank">{{res 'setHelpWebApp'}}</a>
</li>

View File

@ -1,6 +1,6 @@
<div class="settings">
<div class="settings__back-button">
<i class="fa fa-chevron-left settings__back-button-pre"></i>{{res 'retToApp'}} <i class="fa fa-external-link-square settings__back-button-post"></i>
<i class="fa fa-chevron-left settings__back-button-pre"></i>{{res 'retToApp'}} <i class="fa fa-arrow-circle-left settings__back-button-post"></i>
</div>
<div class="scroller">
</div>

View File

@ -15,7 +15,7 @@
{{#each files as |file|}}
{{#unless file.dir}}
<div class="open-list__file {{#unless file.kdbx}}open-list__file--another{{/unless}}" data-path="{{file.path}}">
<i class="open-list__file-icon fa fa-{{#if file.kdbx}}key{{else}}file-text-o{{/if}}"></i>
<i class="open-list__file-icon fa fa-{{#if file.kdbx}}keeweb{{else}}file-text-o{{/if}}"></i>
<span class="open-list__file-text">{{file.name}}</span>
</div>
{{/unless}}

View File

@ -1,6 +1,6 @@
<div class="tag">
<div class="back-button">
{{res 'retToApp'}} <i class="fa fa-external-link-square"></i>
{{res 'retToApp'}} <i class="fa fa-arrow-circle-left"></i>
</div>
<h1>{{res 'tagTitle'}}</h1>
<div class="tag__field">
@ -10,6 +10,6 @@
</div>
<div class="tag__space"></div>
<div class="tag__buttons">
<i class="tag__buttons-trash fa fa-trash-o" title="{{res 'tagTrash'}}" tip-placement="right"></i>
<i class="tag__buttons-trash fa fa-trash-alt" title="{{res 'tagTrash'}}" tip-placement="right"></i>
</div>
</div>

View File

@ -0,0 +1,108 @@
const fs = require('fs');
const path = require('path');
const SVGIcons2SVGFontStream = require('svgicons2svgfont');
const svg2ttf = require('svg2ttf');
const wawoff2 = require('wawoff2');
const svgBaseDir = path.resolve('node_modules/@fortawesome/fontawesome-free/svgs/');
const svgDirs = ['brands', 'regular', 'solid']
.map((dir) => path.join(svgBaseDir, dir))
.concat('graphics/svg');
const allIcons = {};
for (const svgDir of svgDirs) {
const suffix = svgDir.endsWith('regular') ? '-o' : '';
fs.readdirSync(path.join(svgDir))
.filter((icon) => icon.endsWith('.svg'))
.forEach((icon) => {
const svgIconPath = path.join(svgDir, icon);
const iconName = icon.substr(0, icon.length - 4) + suffix;
allIcons[iconName] = svgIconPath;
});
}
module.exports = function makeFontAwesomeWoff2() {
const callback = this.async();
if (this.cacheable) {
this.cacheable();
}
const iconFontScssPath = path.resolve('app/styles/base/_icon-font.scss');
this.addDependency(iconFontScssPath);
fs.readFile(iconFontScssPath, 'utf-8', async (err, scssSource) => {
if (err) {
return callback(err);
}
process.stdout.write('Building fontawesome.woff2... ');
const startTime = Date.now();
try {
const { fontData, iconsCount } = await buildFont(this, scssSource);
const kb = (fontData.byteLength / 1024).toFixed(2);
const time = Date.now() - startTime;
process.stdout.write(`ok: ${time}ms, ${iconsCount} icons, ${kb} KiB\n`);
const fontCss = fontData.toString('base64');
callback(null, `module.exports = "data:font/woff2;base64,${fontCss}"`);
} catch (ex) {
process.stdout.write('error\n');
callback(ex);
}
});
};
function buildFont(loader, scssSource) {
const includedIcons = {};
const includedIconList = [...scssSource.matchAll(/\n\$fa-var-([\w-]+):/g)].map(
([, name]) => name
);
for (const iconName of includedIconList) {
if (includedIcons[iconName]) {
throw new Error(`Duplicate icon: $fa-var-${iconName}`);
}
if (!allIcons[iconName]) {
throw new Error(`Icon not found: "${iconName}"`);
}
includedIcons[iconName] = true;
}
const fontStream = new SVGIcons2SVGFontStream({
fontName: 'Font Awesome 5 Free',
round: 10e12,
log() {}
});
const fontData = [];
fontStream.on('data', (chunk) => fontData.push(chunk));
let charCode = 0xf000;
for (const iconName of includedIconList) {
++charCode;
const svgIconPath = allIcons[iconName];
loader.addDependency(svgIconPath);
const glyph = fs.createReadStream(svgIconPath);
glyph.metadata = { name: iconName, unicode: [String.fromCharCode(charCode)] };
fontStream.write(glyph);
}
fontStream.end();
return new Promise((resolve, reject) => {
fontStream.on('end', async () => {
try {
let data = Buffer.concat(fontData);
data = Buffer.from(svg2ttf(data.toString('utf8')).buffer);
data = Buffer.from(await wawoff2.compress(data));
resolve({ fontData: data, iconsCount: includedIconList.length });
} catch (ex) {
reject(ex);
}
});
});
}
module.exports.raw = true;

View File

@ -0,0 +1,23 @@
const fs = require('fs');
const path = require('path');
module.exports = function loadScss(scssSource) {
const callback = this.async();
const iconFontScssPath = path.resolve('app/styles/base/_icon-font.scss');
this.addDependency(iconFontScssPath);
fs.readFile(iconFontScssPath, 'utf-8', (err, iconFontScssSource) => {
if (err) {
return callback(err);
}
scssSource +=
'\n' +
[...iconFontScssSource.matchAll(/\n\$fa-var-([\w-]+):/g)]
.map(([, name]) => name)
.map((icon) => `.fa-${icon}:before { content: $fa-var-${icon}; }`)
.join('\n');
callback(null, scssSource);
});
};

View File

@ -62,7 +62,7 @@ function config(options) {
'public-key.pem': path.join(rootDir, 'app/resources/public-key.pem'),
'public-key-new.pem': path.join(rootDir, 'app/resources/public-key-new.pem'),
'demo.kdbx': path.join(rootDir, 'app/resources/Demo.kdbx'),
svg: path.join(rootDir, 'app/resources/svg')
'fontawesome.woff2': '@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2'
},
fallback: {
console: false,
@ -77,6 +77,9 @@ function config(options) {
moment: false
}
},
resolveLoader: {
modules: ['node_modules', path.join(__dirname, 'loaders')]
},
module: {
rules: [
{
@ -166,17 +169,13 @@ function config(options) {
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { sourceMap: devMode } },
{ loader: 'postcss-loader', options: { sourceMap: devMode } },
{ loader: 'sass-loader', options: { sourceMap: devMode } }
{ loader: 'sass-loader', options: { sourceMap: devMode } },
{ loader: 'scss-add-icons-loader' }
]
},
{
test: /fonts[\\/].*\.(woff|ttf|eot|svg)$/,
use: ['base64-inline-loader', 'ignore-loader']
},
{ test: /\.woff2$/, loader: 'base64-inline-loader' },
{ test: /fontawesome.*\.woff2$/, loader: 'fontawesome-loader' },
{ test: /\.pem$/, loader: 'raw-loader' },
{ test: /\.kdbx$/, loader: 'base64-loader' },
{ test: /\.svg$/, loader: 'raw-loader' }
{ test: /\.kdbx$/, loader: 'base64-loader' }
]
},
optimization: {

1
graphics/svg/keeweb.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M136.736 512c-4.892-.008-10.322-2.061-15.92-4.997-11.941-6.265-20.13-14.185-13.293-27.218l166.101-316.638c-1.972-1.022-3.619-1.88-4.743-2.469-59.892-31.418-86.463-77.87-64.952-118.877 24.726-47.135 101.304-55.69 171.042-19.107 69.738 36.584 106.227 104.451 81.501 151.586-21.264 40.536-76.784 44.151-132.61 14.866-1.538-.807-4.033-2.103-6.857-3.567L150.768 502.471c-3.632 6.924-8.488 9.538-14.032 9.529zm-30.582-67.835l-3.144-1.649-.7-.366-42.546-22.32v-.001l-10.256-5.38c-1.738-.911-2.407-3.057-1.496-4.794l13.465-25.667c.906-1.728 3.036-2.399 4.768-1.509l.028.013 20.513 10.761c1.736.911 3.883.241 4.794-1.496l13.466-25.667c.911-1.737.24-3.883-1.497-4.794l-10.256-5.382-10.256-5.38c-1.737-.911-2.406-3.057-1.495-4.794l13.464-25.669c.911-1.737 3.058-2.406 4.794-1.494l10.258 5.38 26.697 14.005 16.548 8.681c.007.003.014.007.021.011l3.125 1.639-14.142 26.957-.973 1.855c0 .001-.001.003-.002.004l-20.063 38.245-2.041 3.888-11.424 21.779c-.002.004-.005.009-.008.014zm67.232-128.162l-3.145-1.651-14.938-7.837-11.794-6.187c-1.737-.911-2.408-3.057-1.497-4.794l13.466-25.667c.911-1.737 3.058-2.408 4.794-1.497l11.795 6.188 14.939 7.837c.007.003.014.007.021.01l3.125 1.64-1.651 3.145-6.731 12.834-6.733 12.833c-.003.005-.006.008-.009.013zm219.778-151.914c8.857.016 15.784-3.552 20.386-12.326 14.027-26.737-11.92-67.987-57.953-92.135-46.032-24.148-94.719-22.049-108.746 4.688-14.026 26.737 24.987 44.293 71.02 68.441 30.928 16.224 57.156 31.296 75.293 31.332z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M301.922 245.228s75.153-30.691 75.481-30.788c24.326-7.153 36.367-3.702 36.367-3.702-21.782-84.997-108.292-136.23-193.227-114.432-38.249 9.817-71.469 33.544-93.178 66.552.52-.013 16.472-4.123 52.398 9.869.961.375 122.159 72.501 122.159 72.501z"/><path d="M193.722 183.738l-.005.016c-20.037-12.418-43.146-18.983-66.716-18.951-.544 0-1.08.035-1.623.042C55.272 165.714-.858 223.292.01 293.451c.315 25.449 8.261 50.218 22.808 71.094l277.548-116.882z"/><path d="M415.757 212.725c-2.306-.154-4.622-.261-6.965-.261-14.069-.014-27.99 2.862-40.903 8.449l-.003-.011-63.547 26.762 195.299 117.067c27.027-50.213 8.262-112.843-41.913-139.89-12.965-6.989-27.275-11.12-41.967-12.116z"/><path d="M24.804 366.531c23.721 34.131 62.641 54.471 104.184 54.449h277.816c37.951.011 72.843-20.83 90.847-54.262L302.352 249.649z"/></svg>

After

Width:  |  Height:  |  Size: 881 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M512 324.266V187.734H386.845v136.532zm-85.334-22.755c-3.141-.001-5.687-2.547-5.688-5.688v-79.645c0-3.141 2.547-5.688 5.688-5.689h45.511c1.509 0 2.956.6 4.023 1.666 1.067 1.067 1.666 2.514 1.666 4.023v79.645c0 1.509-.599 2.956-1.666 4.023-1.067 1.067-2.514 1.666-4.023 1.666h-45.511z"/><path d="M432.355 250.311v-28.445h34.134v28.445zm0 39.822v-28.445h34.134v28.445zM0 172.562v166.876C0 349.893 8.507 358.4 18.962 358.4h26.549V193.422c.045-3.11 2.579-5.606 5.688-5.606 3.11 0 5.643 2.496 5.689 5.606V358.4h299.615c10.456 0 18.963-8.507 18.963-18.962V172.562c0-10.455-8.507-18.962-18.963-18.962H18.962C8.506 153.6 0 162.107 0 172.562zm295.368 83.751c.148 11.765-9.192 21.112-20.958 21.262-11.426-.432-20.774-9.774-20.341-21.201-.149-11.765 9.191-21.113 20.619-20.679 11.765-.152 21.112 9.19 20.68 20.618zm-51.18-34.829c1.304.76 2.253 2.006 2.637 3.465.384 1.459.173 3.011-.587 4.314-4.719 8.096-7.214 17.417-7.214 26.959v.017c-.174 9.953 2.132 19.047 6.841 27.11 1.566 2.712.647 6.18-2.058 7.759-2.704 1.579-6.176.676-7.768-2.021-5.775-9.887-8.615-20.993-8.391-32.943v-.026c0-11.452 3.028-22.753 8.761-32.584.759-1.304 2.006-2.253 3.465-2.637 1.459-.385 3.011-.173 4.314.587zm-28.934-21.34c1.269.816 2.161 2.104 2.481 3.579.319 1.474.04 3.016-.778 4.284-9.431 14.642-14.381 31.281-14.178 48.109-.2 17.442 4.632 34.222 13.829 48.579 1.695 2.646.924 6.165-1.723 7.86-2.646 1.694-6.165.923-7.859-1.723-10.391-16.223-15.76-35.168-15.626-54.712-.159-18.927 5.356-37.758 15.992-54.273 1.701-2.641 5.221-3.404 7.862-1.703zm-27.387-20.439c1.254.841 2.122 2.145 2.413 3.625.291 1.481-.018 3.017-.86 4.269-13.596 20.254-20.845 43.873-20.967 68.301-.298 24.616 6.711 48.369 20.273 68.783 1.701 2.615.978 6.112-1.621 7.839-2.598 1.727-6.102 1.039-7.855-1.542-14.529-21.871-22.185-47.259-22.185-73.525 0-.552.003-1.1.01-1.653.131-26.633 8.05-52.424 22.898-74.544 1.751-2.608 5.285-3.304 7.894-1.553z"/></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -9,7 +9,6 @@ module.exports = function (grunt) {
'copy:favicon',
'copy:icons',
'copy:manifest',
'copy:fonts',
'webpack:app',
'inline',
'htmlmin',

127
package-lock.json generated
View File

@ -1908,6 +1908,11 @@
}
}
},
"@fortawesome/fontawesome-free": {
"version": "5.15.1",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.1.tgz",
"integrity": "sha512-OEdH7SyC1suTdhBGW91/zBfR6qaIhThbcN8PUXtXilY4GYnSBbVqOntdHbC1vXwsDnX0Qix2m2+DSU1J51ybOQ=="
},
"@google-cloud/common": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.5.0.tgz",
@ -4869,6 +4874,11 @@
}
}
},
"cubic2quad": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cubic2quad/-/cubic2quad-1.1.1.tgz",
"integrity": "sha1-abGcYaP1tB7PLx1fro+wNBWqixU="
},
"cuint": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz",
@ -6775,11 +6785,6 @@
}
}
},
"font-awesome": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
"integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@ -7583,6 +7588,11 @@
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="
},
"geometry-interfaces": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz",
"integrity": "sha512-qD6OdkT6NcES9l4Xx3auTpwraQruU7dARbQPVO71MKvkGYw5/z/oIiGymuFXrRaEQa5Y67EIojUpaLeGEa5hGA=="
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@ -10614,6 +10624,11 @@
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"microbuffer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/microbuffer/-/microbuffer-1.0.0.tgz",
"integrity": "sha1-izgy7UDIfVH0e7I0kTppinVtGdI="
},
"micromatch": {
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
@ -11223,6 +11238,14 @@
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
},
"neatequal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/neatequal/-/neatequal-1.0.0.tgz",
"integrity": "sha1-LuEhG8n6bkxVcV/SELsFYC6xrjs=",
"requires": {
"varstream": "^0.3.2"
}
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@ -15357,6 +15380,16 @@
}
}
},
"string.fromcodepoint": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/string.fromcodepoint/-/string.fromcodepoint-0.2.1.tgz",
"integrity": "sha1-jZeDM8C8klOPUPOD5IiPPlYZ1lM="
},
"string.prototype.codepointat": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
},
"string.prototype.trimend": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz",
@ -15610,6 +15643,41 @@
"has-flag": "^3.0.0"
}
},
"svg-pathdata": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-5.0.5.tgz",
"integrity": "sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow=="
},
"svg2ttf": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/svg2ttf/-/svg2ttf-5.0.0.tgz",
"integrity": "sha512-xv4ERtuuaY+RQu7G57nKF7agrAGP+Bqmox72+kIbKek5vyAo02Dus901fR995p0E6adc27+kRhPVynDdShUWWw==",
"requires": {
"argparse": "^1.0.6",
"cubic2quad": "^1.0.0",
"lodash": "^4.17.10",
"microbuffer": "^1.0.0",
"svgpath": "^2.1.5",
"xmldom": "~0.1.22"
}
},
"svgicons2svgfont": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-9.1.1.tgz",
"integrity": "sha512-iOj7lqHP/oMrLg7S2Iv89LOJUfmIuePefXcs5ul4IsKwcYvL/T/Buahz+nQQJygyuvEMBBXqnCRmnvJggHeJzA==",
"requires": {
"commander": "^2.12.2",
"geometry-interfaces": "^1.1.4",
"glob": "^7.1.2",
"neatequal": "^1.0.0",
"readable-stream": "^2.3.3",
"sax": "^1.2.4",
"string.fromcodepoint": "^0.2.1",
"string.prototype.codepointat": "^0.2.0",
"svg-pathdata": "^5.0.0",
"transformation-matrix-js": "^2.7.1"
}
},
"svgo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
@ -15630,6 +15698,11 @@
"util.promisify": "~1.0.0"
}
},
"svgpath": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.3.0.tgz",
"integrity": "sha512-N/4UDu3Y2ICik0daMmFW1tplw0XPs1nVIEVYkTiQfj9/JQZeEtAKaSYwheCwje1I4pQ5r22fGpoaNIvGgsyJyg=="
},
"table": {
"version": "5.4.6",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
@ -16079,6 +16152,11 @@
"punycode": "^2.1.1"
}
},
"transformation-matrix-js": {
"version": "2.7.6",
"resolved": "https://registry.npmjs.org/transformation-matrix-js/-/transformation-matrix-js-2.7.6.tgz",
"integrity": "sha512-1CxDIZmCQ3vA0GGnkdMQqxUXVm3xXAFmglPYRS1hr37LzSg22TC7QAWOT38OmdUvMEs/rqcnkFoAsqvzdiluDg=="
},
"trim-newlines": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
@ -16594,6 +16672,37 @@
"spdx-expression-parse": "^3.0.0"
}
},
"varstream": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/varstream/-/varstream-0.3.2.tgz",
"integrity": "sha1-GKxklHZfP/GjWtmkvgU77BiKXeE=",
"requires": {
"readable-stream": "^1.0.33"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@ -16623,6 +16732,14 @@
"graceful-fs": "^4.1.2"
}
},
"wawoff2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wawoff2/-/wawoff2-1.0.2.tgz",
"integrity": "sha512-qxuTwf5tAP/XojrRc6cmR0hGvqgD3XUxv2fzfzURKPDfE7AeHmtRuankVxdJ4DRdSKXaE5QlyJT49yBis2vb6Q==",
"requires": {
"argparse": "^1.0.6"
}
},
"wbuf": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",

View File

@ -15,6 +15,7 @@
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-optional-chaining": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"@fortawesome/fontawesome-free": "^5.15.1",
"@keeweb/keeweb-native-modules": "https://github.com/keeweb/keeweb-native-modules/releases/download/0.4.1/keeweb-native-modules.tgz",
"adm-zip": "^0.4.16",
"argon2-browser": "1.15.2",
@ -44,7 +45,6 @@
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-standard": "4.1.0",
"exports-loader": "1.1.1",
"font-awesome": "4.7.0",
"fs-extra": "^9.0.1",
"grunt": "1.3.0",
"grunt-chmod": "^1.1.1",
@ -91,9 +91,12 @@
"string-replace-loader": "^3.0.1",
"strip-sourcemap-loader": "0.0.1",
"sumchecker": "^3.0.1",
"svg2ttf": "^5.0.0",
"svgicons2svgfont": "^9.1.1",
"terser-webpack-plugin": "^5.0.3",
"time-grunt": "2.0.0",
"url-loader": "^4.1.1",
"wawoff2": "^1.0.2",
"webpack": "^5.6.0",
"webpack-bundle-analyzer": "^4.1.0",
"webpack-dev-server": "^3.11.0"