1
0
Fork 0
mirror of https://github.com/wallabag/wallabag.git synced 2025-06-27 16:36:00 +00:00

Merge pull request #8031 from wallabag/use-stimulus

Use Stimulus
This commit is contained in:
Yassine Guedidi 2025-04-07 18:40:31 +02:00 committed by GitHub
commit 387224f830
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 781 additions and 691 deletions

11
assets/bootstrap.js vendored Normal file
View file

@ -0,0 +1,11 @@
import { startStimulusApp } from '@symfony/stimulus-bridge';
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
export default startStimulusApp(require.context(
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
true,
/\.[jt]sx?$/,
));
// register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController);

4
assets/controllers.json Normal file
View file

@ -0,0 +1,4 @@
{
"controllers": [],
"entrypoints": []
}

View file

@ -0,0 +1,13 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['input'];
toggle() {
this.element.classList.toggle('hidden');
if (!this.element.classList.contains('hidden')) {
this.inputTarget.focus();
}
}
}

View file

@ -0,0 +1,57 @@
import { Controller } from '@hotwired/stimulus';
import annotator from 'annotator';
export default class extends Controller {
static values = {
entryId: Number,
createUrl: String,
updateUrl: String,
destroyUrl: String,
searchUrl: String,
};
connect() {
this.app = new annotator.App();
this.app.include(annotator.ui.main, {
element: this.element,
});
const authorization = {
permits() { return true; },
};
this.app.registry.registerUtility(authorization, 'authorizationPolicy');
this.app.include(annotator.storage.http, {
prefix: '',
urls: {
create: this.createUrlValue,
update: this.updateUrlValue,
destroy: this.destroyUrlValue,
search: this.searchUrlValue,
},
entryId: this.entryIdValue,
onError(msg, xhr) {
if (!Object.prototype.hasOwnProperty.call(xhr, 'responseJSON')) {
annotator.notification.banner('An error occurred', 'error');
return;
}
Object.values(xhr.responseJSON.children).forEach((v) => {
if (v.errors) {
Object.values(v.errors).forEach((errorText) => {
annotator.notification.banner(errorText, 'error');
});
}
});
},
});
this.app.start().then(() => {
this.app.annotations.load({ entry: this.entryIdValue });
});
}
disconnect() {
this.app.destroy();
}
}

View file

@ -0,0 +1,15 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['item', 'tagAction'];
toggleSelection(e) {
this.itemTargets.forEach((item) => {
item.checked = e.currentTarget.checked; // eslint-disable-line no-param-reassign
});
}
tagSelection() {
this.element.requestSubmit(this.tagActionTarget);
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
import ClipboardJS from 'clipboard';
export default class extends Controller {
connect() {
this.clipboard = new ClipboardJS(this.element);
this.clipboard.on('success', (e) => {
e.clearSelection();
});
}
disconnect() {
this.clipboard.destroy();
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['previewArticle', 'previewContent', 'font', 'fontSize', 'lineHeight', 'maxWidth'];
connect() {
this.updatePreview();
}
updatePreview() {
this.previewArticleTarget.style.maxWidth = `${this.maxWidthTarget.value}em`;
this.previewContentTarget.style.fontFamily = this.fontTarget.value;
this.previewContentTarget.style.fontSize = `${this.fontSizeTarget.value}em`;
this.previewContentTarget.style.lineHeight = `${this.lineHeightTarget.value}em`;
}
}

View file

@ -0,0 +1,39 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect() {
this.#choose();
this.mql = window.matchMedia('(prefers-color-scheme: dark)');
this.mql.addEventListener('change', this.#choose.bind(this));
}
useLight() {
this.element.classList.remove('dark-theme');
document.cookie = 'theme=light;samesite=Lax;path=/;max-age=31536000';
}
useDark() {
this.element.classList.add('dark-theme');
document.cookie = 'theme=dark;samesite=Lax;path=/;max-age=31536000';
}
useAuto() {
document.cookie = 'theme=auto;samesite=Lax;path=/;max-age=0';
this.#choose();
}
#choose() {
const themeCookieExists = document.cookie.split(';').some((cookie) => cookie.trim().startsWith('theme='));
if (themeCookieExists) {
return;
}
if (this.mql.matches) {
this.element.classList.add('dark-theme');
} else {
this.element.classList.remove('dark-theme');
}
}
}

View file

@ -0,0 +1,58 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['card', 'paginationWrapper'];
connect() {
this.pagination = this.paginationWrapperTarget.querySelector('.pagination');
this.cardIndex = 0;
this.lastCardIndex = this.cardTargets.length - 1;
/* If we come from next page */
if (window.location.hash === '#prev') {
this.cardIndex = this.lastCardIndex;
}
this.currentCard = this.cardTargets[this.cardIndex];
this.currentCard.classList.add('z-depth-4');
}
selectRightCard() {
if (this.cardIndex >= 0 && this.cardIndex < this.lastCardIndex) {
this.currentCard.classList.remove('z-depth-4');
this.cardIndex += 1;
this.currentCard = this.cardTargets[this.cardIndex];
this.currentCard.classList.add('z-depth-4');
return;
}
if (this.pagination && this.pagination.querySelector('a[rel="next"]')) {
window.location.href = this.pagination.querySelector('a[rel="next"]').href;
}
}
selectLeftCard() {
if (this.cardIndex > 0 && this.cardIndex <= this.lastCardIndex) {
this.currentCard.classList.remove('z-depth-4');
this.cardIndex -= 1;
this.currentCard = this.cardTargets[this.cardIndex];
this.currentCard.classList.add('z-depth-4');
return;
}
if (this.pagination && this.pagination.querySelector('a[rel="prev"]')) {
window.location.href = `${this.pagination.querySelector('a[rel="prev"]').href}#prev`;
}
}
selectCurrentCard() {
const url = this.currentCard.querySelector('a.card-title').href;
if (url) {
window.location.href = url;
}
}
}

View file

@ -0,0 +1,13 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['emailTwoFactor', 'googleTwoFactor'];
uncheckGoogle() {
this.googleTwoFactorTarget.checked = false;
}
uncheckEmail() {
this.emailTwoFactorTarget.checked = false;
}
}

View file

@ -0,0 +1,11 @@
import { Controller } from '@hotwired/stimulus';
import 'highlight.js/styles/atom-one-light.css';
import hljs from 'highlight.js';
export default class extends Controller {
connect() {
this.element.querySelectorAll('pre code').forEach((element) => {
hljs.highlightElement(element);
});
}
}

View file

@ -0,0 +1,7 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
toggleAddTagForm() {
this.dispatch('toggleAddTagForm');
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
static values = {
accordion: { type: Boolean, default: true },
};
connect() {
this.instance = M.Collapsible.init(this.element, { accordion: this.accordionValue });
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.Dropdown.init(this.element, {
hover: false,
coverTrigger: false,
constrainWidth: false,
});
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,32 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
static values = {
edge: { type: String, default: 'left' },
};
connect() {
this.instance = M.FloatingActionButton.init(this.element);
}
autoDisplay() {
const scrolled = (window.innerHeight + window.scrollY) >= document.body.offsetHeight;
if (scrolled) {
this.toggleScroll = true;
this.instance.open();
} else if (this.toggleScroll === true) {
this.toggleScroll = false;
this.instance.close();
}
}
click() {
this.dispatch('click');
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.FormSelect.init(this.element.querySelector('select'));
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,24 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
const mobileMaxWidth = 993;
export default class extends Controller {
static values = {
edge: { type: String, default: 'left' },
};
connect() {
this.instance = M.Sidenav.init(this.element, { edge: this.edgeValue });
}
close() {
if (window.innerWidth < mobileMaxWidth) {
this.instance.close();
}
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.Tabs.init(this.element);
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.toast({ text: this.element.innerText });
}
disconnect() {
this.instance.dismissAll();
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
import M from '@materializecss/materialize';
export default class extends Controller {
connect() {
this.instance = M.Tooltip.init(this.element);
}
disconnect() {
this.instance.destroy();
}
}

View file

@ -0,0 +1,10 @@
import { Controller } from '@hotwired/stimulus';
import jrQrcode from 'jr-qrcode';
export default class extends Controller {
static values = { url: String };
connect() {
this.element.setAttribute('src', jrQrcode.getQrBase64(this.urlValue));
}
}

View file

@ -0,0 +1,10 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
updateWidth() {
const referenceHeight = document.body.offsetHeight - window.innerHeight;
const scrollPercent = (window.scrollY / referenceHeight) * 100;
this.element.style.width = `${scrollPercent}%`;
}
}

View file

@ -0,0 +1,19 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static values = { entryId: Number };
connect() {
window.scrollTo({
top: window.innerHeight * localStorage[`wallabag.article.${this.entryIdValue}.percent`],
behavior: 'smooth',
});
}
saveScroll() {
const scrollPercent = window.scrollY / window.innerHeight;
const scrollPercentRounded = Math.round(scrollPercent * 100) / 100;
localStorage[`wallabag.article.${this.entryIdValue}.percent`] = scrollPercentRounded;
}
}

View file

@ -0,0 +1,141 @@
import { Controller } from '@hotwired/stimulus';
import Mousetrap from 'mousetrap';
export default class extends Controller {
static targets = ['openOriginal', 'markAsFavorite', 'markAsRead', 'deleteEntry', 'showAddUrl', 'showSearch', 'showActions'];
static outlets = ['entries-navigation'];
connect() {
/* Go to */
Mousetrap.bind('g u', () => {
window.location.href = Routing.generate('homepage');
});
Mousetrap.bind('g s', () => {
window.location.href = Routing.generate('starred');
});
Mousetrap.bind('g r', () => {
window.location.href = Routing.generate('archive');
});
Mousetrap.bind('g a', () => {
window.location.href = Routing.generate('all');
});
Mousetrap.bind('g t', () => {
window.location.href = Routing.generate('tag');
});
Mousetrap.bind('g c', () => {
window.location.href = Routing.generate('config');
});
Mousetrap.bind('g i', () => {
window.location.href = Routing.generate('import');
});
Mousetrap.bind('g d', () => {
window.location.href = Routing.generate('developer');
});
Mousetrap.bind('?', () => {
window.location.href = Routing.generate('howto');
});
Mousetrap.bind('g l', () => {
window.location.href = Routing.generate('fos_user_security_logout');
});
/* open original article */
Mousetrap.bind('o', () => {
if (!this.hasOpenOriginalTarget) {
return;
}
this.openOriginalTarget.click();
});
/* mark as favorite */
Mousetrap.bind('f', () => {
if (!this.hasMarkAsFavoriteTarget) {
return;
}
this.markAsFavoriteTarget.click();
});
/* mark as read */
Mousetrap.bind('a', () => {
if (!this.hasMarkAsReadTarget) {
return;
}
this.markAsReadTarget.click();
});
/* delete */
Mousetrap.bind('del', () => {
if (!this.hasDeleteEntryTarget) {
return;
}
this.deleteEntryTarget.click();
});
/* Actions */
Mousetrap.bind('g n', (e) => {
if (!this.hasShowAddUrlTarget) {
return;
}
e.preventDefault();
this.showAddUrlTarget.click();
});
Mousetrap.bind('s', (e) => {
if (!this.hasShowSearchTarget) {
return;
}
e.preventDefault();
this.showSearchTarget.click();
});
Mousetrap.bind('esc', (e) => {
if (!this.hasShowActionsTarget) {
return;
}
e.preventDefault();
this.showActionsTarget.click();
});
const originalStopCallback = Mousetrap.prototype.stopCallback;
Mousetrap.prototype.stopCallback = (e, element, combo) => {
// allow esc key to be used in input fields of topbar
if (combo === 'esc' && element.dataset.topbarTarget !== undefined) {
return false;
}
return originalStopCallback(e, element);
};
Mousetrap.bind('right', () => {
if (!this.hasEntriesNavigationOutlet) {
return;
}
this.entriesNavigationOutlet.selectRightCard();
});
Mousetrap.bind('left', () => {
if (!this.hasEntriesNavigationOutlet) {
return;
}
this.entriesNavigationOutlet.selectLeftCard();
});
Mousetrap.bind('enter', () => {
if (!this.hasEntriesNavigationOutlet) {
return;
}
this.entriesNavigationOutlet.selectCurrentCard();
});
}
}

View file

@ -0,0 +1,7 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
toggle() {
this.element.classList.toggle('entry-nav-top--sticky');
}
}

View file

@ -0,0 +1,12 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['link', 'edit', 'form', 'input'];
showForm() {
this.formTarget.classList.remove('hidden');
this.editTarget.classList.add('hidden');
this.linkTarget.classList.add('hidden');
this.inputTarget.focus();
}
}

View file

@ -0,0 +1,31 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['addUrl', 'addUrlInput', 'search', 'searchInput', 'actions'];
showAddUrl() {
this.actionsTarget.style.display = 'none';
this.addUrlTarget.style.display = 'flex';
this.searchTarget.style.display = 'none';
this.addUrlInputTarget.focus();
}
submittingUrl(e) {
e.currentTarget.disabled = true;
this.addUrlInputTarget.readOnly = true;
this.addUrlInputTarget.blur();
}
showSearch() {
this.actionsTarget.style.display = 'none';
this.addUrlTarget.style.display = 'none';
this.searchTarget.style.display = 'flex';
this.searchInputTarget.focus();
}
showActions() {
this.actionsTarget.style.display = 'flex';
this.addUrlTarget.style.display = 'none';
this.searchTarget.style.display = 'none';
}
}

View file

@ -1,18 +1,11 @@
import $ from 'jquery'; import './bootstrap';
/* Materialize imports */ /* Materialize imports */
import '@materializecss/materialize/dist/css/materialize.css'; import '@materializecss/materialize/dist/css/materialize.css';
import M from '@materializecss/materialize/dist/js/materialize'; import '@materializecss/materialize/dist/js/materialize';
/* Annotations */
import annotator from 'annotator';
import ClipboardJS from 'clipboard';
import 'mathjax/es5/tex-svg'; import 'mathjax/es5/tex-svg';
/* jrQrcode */
import jrQrcode from 'jr-qrcode';
/* Fonts */ /* Fonts */
import 'material-design-icons-iconfont/dist/material-design-icons.css'; import 'material-design-icons-iconfont/dist/material-design-icons.css';
import 'lato-font/css/lato-font.css'; import 'lato-font/css/lato-font.css';
@ -22,371 +15,5 @@ import '@fontsource/eb-garamond';
import '@fontsource/montserrat'; import '@fontsource/montserrat';
import '@fontsource/oswald'; import '@fontsource/oswald';
/* Highlight */
import './js/highlight';
/* Tools */
import {
savePercent, retrievePercent, initPreviewText,
} from './js/tools';
/* Import shortcuts */
import './js/shortcuts/main';
import './js/shortcuts/entry';
/* Theme style */ /* Theme style */
import './scss/index.scss'; import './scss/index.scss';
const mobileMaxWidth = 993;
/* ==========================================================================
Annotations & Remember position
========================================================================== */
$(document).ready(() => {
if ($('#article').length) {
const app = new annotator.App();
app.include(annotator.ui.main, {
element: document.querySelector('article'),
});
const authorization = {
permits() { return true; },
};
app.registry.registerUtility(authorization, 'authorizationPolicy');
const x = JSON.parse($('#annotationroutes').html());
app.include(annotator.storage.http, $.extend({}, x, {
onError(msg, xhr) {
if (!Object.prototype.hasOwnProperty.call(xhr, 'responseJSON')) {
annotator.notification.banner('An error occurred', 'error');
return;
}
$.each(xhr.responseJSON.children, (k, v) => {
if (v.errors) {
$.each(v.errors, (n, errorText) => {
annotator.notification.banner(errorText, 'error');
});
}
});
},
}));
app.start().then(() => {
app.annotations.load({ entry: x.entryId });
});
$(window).scroll(() => {
const scrollTop = $(window).scrollTop();
const docHeight = $(document).height();
const scrollPercent = (scrollTop) / (docHeight);
const scrollPercentRounded = Math.round(scrollPercent * 100) / 100;
savePercent(x.entryId, scrollPercentRounded);
});
retrievePercent(x.entryId);
$(window).resize(() => {
retrievePercent(x.entryId, true);
});
}
document.querySelectorAll('[data-handler=tag-rename]').forEach((item) => {
const current = item;
current.wallabag_edit_mode = false;
current.onclick = (event) => {
const target = event.currentTarget;
if (target.wallabag_edit_mode === false) {
$(target.parentNode.querySelector('[data-handle=tag-link]')).addClass('hidden');
$(target.parentNode.querySelector('[data-handle=tag-rename-form]')).removeClass('hidden');
target.parentNode.querySelector('[data-handle=tag-rename-form] input').focus();
target.querySelector('.material-icons').innerHTML = 'done';
target.wallabag_edit_mode = true;
} else {
target.parentNode.querySelector('[data-handle=tag-rename-form]').submit();
}
};
});
// mimic radio button because emailTwoFactor is a boolean
$('#update_user_googleTwoFactor').on('change', () => {
$('#update_user_emailTwoFactor').prop('checked', false);
});
$('#update_user_emailTwoFactor').on('change', () => {
$('#update_user_googleTwoFactor').prop('checked', false);
});
// same mimic for super admin
$('#user_googleTwoFactor').on('change', () => {
$('#user_emailTwoFactor').prop('checked', false);
});
$('#user_emailTwoFactor').on('change', () => {
$('#user_googleTwoFactor').prop('checked', false);
});
// handle copy to clipboard for developer stuff
const clipboard = new ClipboardJS('.btn');
clipboard.on('success', (e) => {
e.clearSelection();
});
});
(function darkTheme() {
const rootEl = document.querySelector('html');
const themeDom = {
darkClass: 'dark-theme',
toggleClass(el) {
return el.classList.toggle(this.darkClass);
},
addClass(el) {
return el.classList.add(this.darkClass);
},
removeClass(el) {
return el.classList.remove(this.darkClass);
},
};
const themeCookie = {
values: {
light: 'light',
dark: 'dark',
},
name: 'theme',
getValue(isDarkTheme) {
return isDarkTheme ? this.values.dark : this.values.light;
},
setCookie(isDarkTheme) {
const value = this.getValue(isDarkTheme);
document.cookie = `${this.name}=${value};samesite=Lax;path=/;max-age=31536000`;
},
removeCookie() {
document.cookie = `${this.name}=auto;samesite=Lax;path=/;max-age=0`;
},
exists() {
return document.cookie.split(';').some((cookie) => cookie.trim().startsWith(`${this.name}=`));
},
};
const preferedColorScheme = {
choose() {
const themeCookieExists = themeCookie.exists();
if (this.isAvailable() && !themeCookieExists) {
const isPreferedColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)').matches === true;
if (!themeCookieExists) {
themeDom[isPreferedColorSchemeDark ? 'addClass' : 'removeClass'](rootEl);
}
}
},
isAvailable() {
return typeof window.matchMedia === 'function';
},
init() {
if (!this.isAvailable()) {
return false;
}
this.choose();
window.matchMedia('(prefers-color-scheme: dark)').addListener(() => {
this.choose();
});
return true;
},
};
const addDarkThemeListeners = () => {
$(document).ready(() => {
const lightThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="light"]');
[...lightThemeButtons].map((lightThemeButton) => {
lightThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.removeClass(rootEl);
themeCookie.setCookie(false);
});
return true;
});
const darkThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="dark"]');
[...darkThemeButtons].map((darkThemeButton) => {
darkThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.addClass(rootEl);
themeCookie.setCookie(true);
});
return true;
});
const autoThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="auto"]');
[...autoThemeButtons].map((autoThemeButton) => {
autoThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeCookie.removeCookie();
preferedColorScheme.choose();
});
return true;
});
});
};
preferedColorScheme.init();
addDarkThemeListeners();
}());
const stickyNav = () => {
const nav = $('.js-entry-nav-top');
$('[data-toggle="actions"]').click(() => {
nav.toggleClass('entry-nav-top--sticky');
});
};
const articleScroll = () => {
const articleEl = $('#article');
if (articleEl.length > 0) {
$(window).scroll(() => {
const s = $(window).scrollTop();
const d = $(document).height();
const c = $(window).height();
const articleElBottom = articleEl.offset().top + articleEl.height();
const scrollPercent = (s / (d - c)) * 100;
$('.progress .determinate').css('width', `${scrollPercent}%`);
const fixedActionBtn = $('.js-fixed-action-btn');
const toggleScrollDataName = 'toggle-auto';
if ((s + c) > articleElBottom) {
fixedActionBtn.data(toggleScrollDataName, true);
fixedActionBtn.floatingActionButton('open');
} else if (fixedActionBtn.data(toggleScrollDataName) === true) {
fixedActionBtn.data(toggleScrollDataName, false);
fixedActionBtn.floatingActionButton('close');
}
});
}
};
$(document).ready(() => {
// sidenav
document.querySelectorAll('.sidenav').forEach((element) => {
$(element).sidenav({ edge: element.getAttribute('data-edge') ?? 'left' });
});
$('select').formSelect();
$('.collapsible[data-collapsible="accordion"]').collapsible();
$('.collapsible[data-collapsible="expandable"]').collapsible({
accordion: false,
});
$('.dropdown-trigger').dropdown({ hover: false });
$('.dropdown-trigger[data-covertrigger="false"][data-constrainwidth="false"]').dropdown({
hover: false,
coverTrigger: false,
constrainWidth: false,
});
$('.tabs').tabs();
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton();
stickyNav();
articleScroll();
initPreviewText();
const toggleNav = (toShow, toFocus) => {
$('.nav-panel-actions').hide();
$(toShow).show();
$(toFocus).focus();
};
$('#nav-btn-add-tag').on('click', () => {
$('.nav-panel-add-tag').toggle();
$('.nav-panel-menu').addClass('hidden');
if (window.innerWidth < mobileMaxWidth) {
$('.sidenav').sidenav('close');
}
$('#tag_label').focus();
return false;
});
$('#nav-btn-add').on('click', () => {
toggleNav('.nav-panel-add', '#entry_url');
return false;
});
$('#config_fontsize').on('input', () => {
const value = $('#config_fontsize').val();
const css = `${value}em`;
$('#preview-content').css('font-size', css);
});
$('#config_font').on('change', () => {
const value = $('#config_font').val();
$('#preview-content').css('font-family', value);
});
$('#config_lineHeight').on('input', () => {
const value = $('#config_lineHeight').val();
const css = `${value}em`;
$('#preview-content').css('line-height', css);
});
$('#config_maxWidth').on('input', () => {
const value = $('#config_maxWidth').val();
const css = `${value}em`;
$('#preview-article').css('max-width', css);
});
const materialAddForm = $('.nav-panel-add');
materialAddForm.on('submit', () => {
materialAddForm.addClass('disabled');
$('input#entry_url', materialAddForm).prop('readonly', true).trigger('blur');
});
$('#nav-btn-search').on('click', () => {
toggleNav('.nav-panel-search', '#search_entry_term');
return false;
});
$('.close').on('click', (e) => {
$(e.target).parent('.nav-panel-item').hide();
$('.nav-panel-actions').show();
return false;
});
const mainCheckboxes = document.querySelectorAll('[data-js="checkboxes-toggle"]');
if (mainCheckboxes.length) {
[...mainCheckboxes].forEach((el) => {
el.addEventListener('click', () => {
const checkboxes = document.querySelectorAll(el.dataset.toggle);
[...checkboxes].forEach((checkbox) => {
const checkboxClone = checkbox;
checkboxClone.checked = el.checked;
});
});
});
}
$('form[name="form_mass_action"] input[name="tags"]').on('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
$('form[name="form_mass_action"] button[name="tag"]').trigger('click');
}
});
document.querySelectorAll('img.jr-qrcode').forEach((qrcode) => {
const src = jrQrcode.getQrBase64(qrcode.getAttribute('data-url'));
qrcode.setAttribute('src', src);
});
document.querySelectorAll('.material-toast').forEach((toast) => {
M.toast({
text: toast.innerText,
});
});
});

View file

@ -1,8 +0,0 @@
import 'highlight.js/styles/atom-one-light.css';
import hljs from 'highlight.js';
window.addEventListener('load', () => {
document.querySelectorAll('pre').forEach((element) => {
hljs.highlightElement(element);
});
});

View file

@ -1,26 +0,0 @@
import Mousetrap from 'mousetrap';
import $ from 'jquery';
$(document).ready(() => {
if ($('#article').length > 0) {
/* open original article */
Mousetrap.bind('o', () => {
$('ul.sidenav a.original i')[0].click();
});
/* mark as favorite */
Mousetrap.bind('f', () => {
$('ul.sidenav a.favorite i')[0].click();
});
/* mark as read */
Mousetrap.bind('a', () => {
$('ul.sidenav a.markasread i')[0].click();
});
/* delete */
Mousetrap.bind('del', () => {
$('ul.sidenav a.delete i')[0].click();
});
}
});

View file

@ -1,104 +0,0 @@
import Mousetrap from 'mousetrap';
import $ from 'jquery';
/* Go to */
Mousetrap.bind('g u', () => { window.location.href = Routing.generate('homepage'); });
Mousetrap.bind('g s', () => { window.location.href = Routing.generate('starred'); });
Mousetrap.bind('g r', () => { window.location.href = Routing.generate('archive'); });
Mousetrap.bind('g a', () => { window.location.href = Routing.generate('all'); });
Mousetrap.bind('g t', () => { window.location.href = Routing.generate('tag'); });
Mousetrap.bind('g c', () => { window.location.href = Routing.generate('config'); });
Mousetrap.bind('g i', () => { window.location.href = Routing.generate('import'); });
Mousetrap.bind('g d', () => { window.location.href = Routing.generate('developer'); });
Mousetrap.bind('?', () => { window.location.href = Routing.generate('howto'); });
Mousetrap.bind('g l', () => { window.location.href = Routing.generate('fos_user_security_logout'); });
function toggleFocus(cardToToogleFocus) {
if (cardToToogleFocus) {
$(cardToToogleFocus).toggleClass('z-depth-4');
}
}
$(document).ready(() => {
const cards = $('#content').find('.card');
const cardNumber = cards.length;
let cardIndex = 0;
/* If we come from next page */
if (window.location.hash === '#prev') {
cardIndex = cardNumber - 1;
}
let card = cards[cardIndex];
const pagination = $('.pagination');
/* Show nothing on quickstart */
if ($('#content > div.quickstart').length > 0) {
return;
}
/* Show nothing on login/register page */
if ($('#username').length > 0 || $('#fos_user_registration_form_username').length > 0) {
return;
}
/* Show nothing on login/register page */
if ($('#username').length > 0 || $('#fos_user_registration_form_username').length > 0) {
return;
}
/* Focus current card */
toggleFocus(card);
/* Actions */
Mousetrap.bind('g n', () => {
$('#nav-btn-add').trigger('click');
return false;
});
Mousetrap.bind('s', () => {
$('#nav-btn-search').trigger('click');
return false;
});
Mousetrap.bind('esc', () => {
$('.close').trigger('click');
});
/* Select right card. If there's a next page, go to next page */
Mousetrap.bind('right', () => {
if (cardIndex >= 0 && cardIndex < cardNumber - 1) {
toggleFocus(card);
cardIndex += 1;
card = cards[cardIndex];
toggleFocus(card);
return;
}
if (pagination.length > 0 && pagination.find('li.next:not(.disabled)').length > 0 && cardIndex === cardNumber - 1) {
window.location.href = window.location.origin + $(pagination).find('li.next a').attr('href');
}
});
/* Select previous card. If there's a previous page, go to next page */
Mousetrap.bind('left', () => {
if (cardIndex > 0 && cardIndex < cardNumber) {
toggleFocus(card);
cardIndex -= 1;
card = cards[cardIndex];
toggleFocus(card);
return;
}
if (pagination.length > 0 && $(pagination).find('li.prev:not(.disabled)').length > 0 && cardIndex === 0) {
window.location.href = `${window.location.origin + $(pagination).find('li.prev a').attr('href')}#prev`;
}
});
Mousetrap.bind('enter', () => {
if (typeof card !== 'object') {
return;
}
const url = $(card).find('.card-title a').attr('href');
if (typeof url === 'string' && url.length > 0) {
window.location.href = window.location.origin + url;
}
});
});

View file

@ -1,54 +0,0 @@
import $ from 'jquery';
function supportsLocalStorage() {
try {
return 'localStorage' in window && window.localStorage !== null;
} catch (e) {
return false;
}
}
function savePercent(id, percent) {
if (!supportsLocalStorage()) { return false; }
localStorage[`wallabag.article.${id}.percent`] = percent;
return true;
}
function retrievePercent(id, resized) {
if (!supportsLocalStorage()) { return false; }
const bheight = $(document).height();
const percent = localStorage[`wallabag.article.${id}.percent`];
const scroll = bheight * percent;
if (!resized) {
window.scrollTo({
top: scroll,
behavior: 'smooth',
});
}
return true;
}
function initPreviewText() {
// no display if preview_text not available
if ($('div').is('#preview-article')) {
const defaultFontFamily = $('#config_font').val();
const defaultFontSize = $('#config_fontsize').val();
const defaultLineHeight = $('#config_lineHeight').val();
const defaultMaxWidth = $('#config_maxWidth').val();
const previewContent = $('#preview-content');
previewContent.css('font-family', defaultFontFamily);
previewContent.css('font-size', `${defaultFontSize}em`);
previewContent.css('line-height', `${defaultLineHeight}em`);
$('#preview-article').css('max-width', `${defaultMaxWidth}em`);
}
}
export {
savePercent,
retrievePercent,
initPreviewText,
};

View file

@ -186,6 +186,14 @@ a.original:not(.waves-effect) {
color: #fff; color: #fff;
} }
.card-tag-labels button {
background: transparent;
border: none;
font-weight: normal;
color: #fff;
cursor: pointer;
}
.card-tag-link { .card-tag-link {
width: calc(100% - 24px); width: calc(100% - 24px);
line-height: 1.3; line-height: 1.3;
@ -196,6 +204,7 @@ a.original:not(.waves-effect) {
.card-tag-form { .card-tag-form {
display: flex; display: flex;
align-items: center;
min-width: 100px; min-width: 100px;
flex-grow: 1; flex-grow: 1;
} }

View file

@ -80,14 +80,14 @@
"@fontsource/eb-garamond": "^5.2.5", "@fontsource/eb-garamond": "^5.2.5",
"@fontsource/montserrat": "^5.2.5", "@fontsource/montserrat": "^5.2.5",
"@fontsource/oswald": "^5.2.5", "@fontsource/oswald": "^5.2.5",
"@hotwired/stimulus": "^3.2.2",
"@materializecss/materialize": "^1.2.2", "@materializecss/materialize": "^1.2.2",
"@symfony/stimulus-bridge": "^4.0.0",
"annotator": "wallabag/annotator#master", "annotator": "wallabag/annotator#master",
"clipboard": "^2.0.11", "clipboard": "^2.0.11",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"highlight.js": "^11.11.1", "highlight.js": "^11.11.1",
"icomoon-free-npm": "^0.0.0", "icomoon-free-npm": "^0.0.0",
"jquery": "^3.7.1",
"jquery.cookie": "^1.4.1",
"jr-qrcode": "^1.2.1", "jr-qrcode": "^1.2.1",
"material-design-icons-iconfont": "^6.7.0", "material-design-icons-iconfont": "^6.7.0",
"mathjax": "^3.2.2", "mathjax": "^3.2.2",
@ -100,7 +100,7 @@
"build:dev": "encore dev", "build:dev": "encore dev",
"watch": "encore dev --watch", "watch": "encore dev --watch",
"build:prod": "encore production --progress", "build:prod": "encore production --progress",
"lint:js": "eslint assets/*.js assets/js/*.js assets/js/**/*.js", "lint:js": "eslint assets/*.js assets/controllers/*.js",
"lint:scss": "stylelint assets/scss/*.scss assets/scss/**/*.scss" "lint:scss": "stylelint assets/scss/*.scss assets/scss/**/*.scss"
} }
} }

View file

@ -10,7 +10,7 @@
<div class="row"> <div class="row">
<div class="tabs-container col s12"> <div class="tabs-container col s12">
<ul class="tabs"> <ul class="tabs" data-controller="materialize--tabs">
<li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'config.tab_menu.settings'|trans }}</a></li> <li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'config.tab_menu.settings'|trans }}</a></li>
<li class="tab col s12 m6 l3"><a href="#set2">{{ 'config.tab_menu.feed'|trans }}</a></li> <li class="tab col s12 m6 l3"><a href="#set2">{{ 'config.tab_menu.feed'|trans }}</a></li>
<li class="tab col s12 m6 l3"><a href="#set3">{{ 'config.tab_menu.user_info'|trans }}</a></li> <li class="tab col s12 m6 l3"><a href="#set3">{{ 'config.tab_menu.user_info'|trans }}</a></li>
@ -21,7 +21,7 @@
</ul> </ul>
</div> </div>
<div id="set1" class="col s12"> <div id="set1" class="col s12" data-controller="config">
{{ form_start(form.config) }} {{ form_start(form.config) }}
{{ form_errors(form.config) }} {{ form_errors(form.config) }}
@ -32,7 +32,7 @@
{{ form_label(form.config.items_per_page) }} {{ form_label(form.config.items_per_page) }}
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_items_per_page'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_items_per_page'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
@ -47,7 +47,7 @@
</label> </label>
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_display_thumbnails'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_display_thumbnails'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
@ -64,14 +64,14 @@
</p> </p>
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_reading_speed'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_reading_speed'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="input-field col s11"> <div class="input-field col s11" data-controller="materialize--form-select">
{{ form_errors(form.config.action_mark_as_read) }} {{ form_errors(form.config.action_mark_as_read) }}
{{ form_widget(form.config.action_mark_as_read) }} {{ form_widget(form.config.action_mark_as_read) }}
{{ form_label(form.config.action_mark_as_read) }} {{ form_label(form.config.action_mark_as_read) }}
@ -79,13 +79,13 @@
</div> </div>
<div class="row"> <div class="row">
<div class="input-field col s11"> <div class="input-field col s11" data-controller="materialize--form-select">
{{ form_errors(form.config.language) }} {{ form_errors(form.config.language) }}
{{ form_widget(form.config.language) }} {{ form_widget(form.config.language) }}
{{ form_label(form.config.language) }} {{ form_label(form.config.language) }}
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_language'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_language'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
@ -102,7 +102,7 @@
</p> </p>
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_pocket_consumer_key'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_pocket_consumer_key'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
@ -112,31 +112,31 @@
<div class="input-field col s12"> <div class="input-field col s12">
<h5>{{ 'config.form_settings.android_configuration'|trans }}</h5> <h5>{{ 'config.form_settings.android_configuration'|trans }}</h5>
<a href="wallabag://{{ app.user.username }}@{{ wallabag_url }}" class="waves-effect waves-light btn hide-on-large-only">{{ 'config.form_settings.android_instruction'|trans }}</a> <a href="wallabag://{{ app.user.username }}@{{ wallabag_url }}" class="waves-effect waves-light btn hide-on-large-only">{{ 'config.form_settings.android_instruction'|trans }}</a>
<img class="hide-on-med-and-down jr-qrcode" alt="{{ 'config.otp.app.qrcode_label'|trans }}" data-url="wallabag://{{ app.user.username }}@{{ wallabag_url }}" /> <img data-controller="qrcode" data-qrcode-url-value="wallabag://{{ app.user.username }}@{{ wallabag_url }}" class="hide-on-med-and-down" alt="{{ 'config.otp.app.qrcode_label'|trans }}" />
</div> </div>
</div> </div>
<h5>{{ 'config.tab_menu.article_display'|trans }}</h5> <h5>{{ 'config.tab_menu.article_display'|trans }}</h5>
<div class="row"> <div class="row">
<div class="input-field col s5"> <div class="input-field col s5" data-controller="materialize--form-select">
{{ form_errors(form.config.font) }} {{ form_errors(form.config.font) }}
{{ form_widget(form.config.font) }} {{ form_widget(form.config.font, {attr: {'data-config-target': 'font', 'data-action': 'config#updatePreview'}}) }}
{{ form_label(form.config.font) }} {{ form_label(form.config.font) }}
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_font'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_font'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
<div class="input-field col s5"> <div class="input-field col s5">
{{ form_errors(form.config.lineHeight) }} {{ form_errors(form.config.lineHeight) }}
{{ form_widget(form.config.lineHeight) }} {{ form_widget(form.config.lineHeight, {attr: {'data-config-target': 'lineHeight', 'data-action': 'config#updatePreview'}}) }}
{{ form_label(form.config.lineHeight, null, {'label_attr': {'class': 'settings-range-label'}}) }} {{ form_label(form.config.lineHeight, null, {'label_attr': {'class': 'settings-range-label'}}) }}
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_lineheight'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_lineheight'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
@ -145,22 +145,22 @@
<div class="row"> <div class="row">
<div class="input-field col s5"> <div class="input-field col s5">
{{ form_errors(form.config.fontsize) }} {{ form_errors(form.config.fontsize) }}
{{ form_widget(form.config.fontsize) }} {{ form_widget(form.config.fontsize, {attr: {'data-config-target': 'fontSize', 'data-action': 'config#updatePreview'}}) }}
{{ form_label(form.config.fontsize, null, {'label_attr': {'class': 'settings-range-label'}}) }} {{ form_label(form.config.fontsize, null, {'label_attr': {'class': 'settings-range-label'}}) }}
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_fontsize'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_fontsize'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
<div class="input-field col s5"> <div class="input-field col s5">
{{ form_errors(form.config.maxWidth) }} {{ form_errors(form.config.maxWidth) }}
{{ form_widget(form.config.maxWidth) }} {{ form_widget(form.config.maxWidth, {attr: {'data-config-target': 'maxWidth', 'data-action': 'config#updatePreview'}}) }}
{{ form_label(form.config.maxWidth, null, {'label_attr': {'class': 'settings-range-label'}}) }} {{ form_label(form.config.maxWidth, null, {'label_attr': {'class': 'settings-range-label'}}) }}
</div> </div>
<div class="input-field col s1"> <div class="input-field col s1">
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_maxwidth'|trans }}"> <a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_maxwidth'|trans }}">
<i class="material-icons">live_help</i> <i class="material-icons">live_help</i>
</a> </a>
</div> </div>
@ -168,8 +168,8 @@
<div class="row"> <div class="row">
<div class="input-field col s12"> <div class="input-field col s12">
<div id="preview-article"> <div id="preview-article" data-config-target="previewArticle">
<article id="preview-content"> <article id="preview-content" data-config-target="previewContent">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</article> </article>
</div> </div>

View file

@ -15,17 +15,17 @@
<p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p> <p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p>
<p> <p>
<img class="hide-on-med-and-down jr-qrcode" data-url="{{ qr_code|raw }}" /> <img data-controller="qrcode" data-qrcode-url-value="{{ qr_code|raw }}" class="hide-on-med-and-down" />
</p> </p>
<p> <div data-controller="highlight">
{{ 'config.otp.app.two_factor_code_description_5'|trans }} <pre>{{ secret }}</pre> {{ 'config.otp.app.two_factor_code_description_5'|trans }} <pre><code>{{ secret }}</code></pre>
</p> </div>
</li> </li>
<li> <li>
<p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p> <p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p>
<p><pre>{{ backupCodes|join("\n") }}</pre></p> <div data-controller="highlight"><pre><code>{{ backupCodes|join("\n") }}</code></pre></div>
</li> </li>
<li> <li>
<p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p> <p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p>

View file

@ -18,14 +18,14 @@
<td>{{ 'developer.client_parameter.field_id'|trans }}</td> <td>{{ 'developer.client_parameter.field_id'|trans }}</td>
<td> <td>
<strong><code>{{ client_id }}</code></strong> <strong><code>{{ client_id }}</code></strong>
<button class="btn" data-clipboard-text="{{ client_id }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button> <button class="btn" data-controller="clipboard" data-clipboard-text="{{ client_id }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>{{ 'developer.client_parameter.field_secret'|trans }}</td> <td>{{ 'developer.client_parameter.field_secret'|trans }}</td>
<td> <td>
<strong><code>{{ client_secret }}</code></strong> <strong><code>{{ client_secret }}</code></strong>
<button class="btn" data-clipboard-text="{{ client_secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button> <button class="btn" data-controller="clipboard" data-clipboard-text="{{ client_secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
</td> </td>
</tr> </tr>
</table> </table>

View file

@ -12,16 +12,16 @@
<p>{{ 'developer.howto.description.paragraph_2'|trans }}</p> <p>{{ 'developer.howto.description.paragraph_2'|trans }}</p>
<p>{{ 'developer.howto.description.paragraph_3'|trans({'%link%': path('developer_create_client')})|raw }}</p> <p>{{ 'developer.howto.description.paragraph_3'|trans({'%link%': path('developer_create_client')})|raw }}</p>
<p>{{ 'developer.howto.description.paragraph_4'|trans }}</p> <p>{{ 'developer.howto.description.paragraph_4'|trans }}</p>
<p> <div data-controller="highlight">
<pre><code class="language-bash">http POST {{ wallabag_url }}/oauth/v2/token \ <pre><code class="language-bash">http POST {{ wallabag_url }}/oauth/v2/token \
grant_type=password \ grant_type=password \
client_id=12_5um6nz50ceg4088c0840wwc0kgg44g00kk84og044ggkscso0k \ client_id=12_5um6nz50ceg4088c0840wwc0kgg44g00kk84og044ggkscso0k \
client_secret=3qd12zpeaxes8cwg8c0404g888co4wo8kc4gcw0occww8cgw4k \ client_secret=3qd12zpeaxes8cwg8c0404g888co4wo8kc4gcw0occww8cgw4k \
username=yourUsername \ username=yourUsername \
password=yourPassw0rd</code></pre> password=yourPassw0rd</code></pre>
</p> </div>
<p>{{ 'developer.howto.description.paragraph_5'|trans }}</p> <p>{{ 'developer.howto.description.paragraph_5'|trans }}</p>
<p> <div data-controller="highlight">
<pre><code class="language-bash">HTTP/1.1 200 OK <pre><code class="language-bash">HTTP/1.1 200 OK
Cache-Control: no-store, private Cache-Control: no-store, private
Connection: close Connection: close
@ -39,12 +39,12 @@ X-Powered-By: PHP/5.5.9-1ubuntu4.13
"scope": null, "scope": null,
"token_type": "bearer" "token_type": "bearer"
}</code></pre> }</code></pre>
</p> </div>
<p>{{ 'developer.howto.description.paragraph_6'|trans }}</p> <p>{{ 'developer.howto.description.paragraph_6'|trans }}</p>
<p> <div data-controller="highlight">
<pre><code class="language-bash">http GET {{ wallabag_url }}/api/entries.json \ <pre><code class="language-bash">http GET {{ wallabag_url }}/api/entries.json \
"Authorization:Bearer ZWFjNjA3ZWMwYWVmYzRkYTBlMmQ3NTllYmVhOGJiZDE0ZTg1NjE4MjczOTVlNzM0ZTRlMWQ0MmRlMmYwNTk5Mw"</code></pre> "Authorization:Bearer ZWFjNjA3ZWMwYWVmYzRkYTBlMmQ3NTllYmVhOGJiZDE0ZTg1NjE4MjczOTVlNzM0ZTRlMWQ0MmRlMmYwNTk5Mw"</code></pre>
</p> </div>
<p>{{ 'developer.howto.description.paragraph_7'|trans }}</p> <p>{{ 'developer.howto.description.paragraph_7'|trans }}</p>
<p>{{ 'developer.howto.description.paragraph_8'|trans({'%link%': path('nelmio_api_doc.swagger_ui')})|raw }}</p> <p>{{ 'developer.howto.description.paragraph_8'|trans({'%link%': path('nelmio_api_doc.swagger_ui')})|raw }}</p>
<p><a href="{{ path('developer') }}" class="waves-effect waves-light grey btn">{{ 'developer.howto.back'|trans }}</a></p> <p><a href="{{ path('developer') }}" class="waves-effect waves-light grey btn">{{ 'developer.howto.back'|trans }}</a></p>

View file

@ -25,7 +25,7 @@
<h4>{{ 'developer.existing_clients.title'|trans }}</h4> <h4>{{ 'developer.existing_clients.title'|trans }}</h4>
{% if clients %} {% if clients %}
<ul class="collapsible" data-collapsible="expandable"> <ul class="collapsible" data-controller="materialize--collapsible" data-materialize--collapsible-accordion-value="false">
{% for client in clients %} {% for client in clients %}
<li> <li>
<div class="collapsible-header">{{ client.name }} - #{{ client.id }}</div> <div class="collapsible-header">{{ client.name }} - #{{ client.id }}</div>
@ -35,14 +35,14 @@
<td>{{ 'developer.existing_clients.field_id'|trans }}</td> <td>{{ 'developer.existing_clients.field_id'|trans }}</td>
<td> <td>
<strong><code>{{ client.clientId }}</code></strong> <strong><code>{{ client.clientId }}</code></strong>
<button class="btn" data-clipboard-text="{{ client.clientId }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button> <button class="btn" data-controller="clipboard" data-clipboard-text="{{ client.clientId }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>{{ 'developer.existing_clients.field_secret'|trans }}</td> <td>{{ 'developer.existing_clients.field_secret'|trans }}</td>
<td> <td>
<strong><code>{{ client.secret }}</code></strong> <strong><code>{{ client.secret }}</code></strong>
<button class="btn" data-clipboard-text="{{ client.secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button> <button class="btn" data-controller="clipboard" data-clipboard-text="{{ client.secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
</td> </td>
</tr> </tr>
<tr> <tr>

View file

@ -1,3 +1,3 @@
<label class="entry-checkbox"> <label class="entry-checkbox">
<input type="checkbox" class="entry-checkbox-input" data-js="entry-checkbox" name="entry-checkbox[]" value="{{ entry.id }}" /> <input type="checkbox" class="entry-checkbox-input" name="entry-checkbox[]" value="{{ entry.id }}" data-batch-edit-target="item" />
</label> </label>

View file

@ -24,21 +24,21 @@
{% block nav_panel_extra_actions %} {% block nav_panel_extra_actions %}
{% if active_route %} {% if active_route %}
<li> <li>
<a class="waves-effect tooltipped js-random-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.random_entry'|trans }}" href="{{ path('random_entry', {'type': active_route}) }}"> <a class="waves-effect js-random-action" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.random_entry'|trans }}" href="{{ path('random_entry', {'type': active_route}) }}">
<i class="material-icons">casino</i> <i class="material-icons">casino</i>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if has_filters %} {% if has_filters %}
<li class="button-filters"> <li class="button-filters">
<a class="nav-panel-menu sidenav-trigger tooltipped js-filters-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.filter_entries'|trans }}" href="#" data-target="filters"> <a class="nav-panel-menu sidenav-trigger js-filters-action" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.filter_entries'|trans }}" href="#" data-target="filters">
<i class="material-icons">filter_list</i> <i class="material-icons">filter_list</i>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if has_exports %} {% if has_exports %}
<li class="button-export"> <li class="button-export">
<a class="nav-panel-menu sidenav-trigger tooltipped js-export-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.export'|trans }}" href="#" data-target="export"> <a class="nav-panel-menu sidenav-trigger js-export-action" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.export'|trans }}" href="#" data-target="export">
<i class="material-icons">file_download</i> <i class="material-icons">file_download</i>
</a> </a>
</li> </li>
@ -53,15 +53,15 @@
{% if current_route == 'homepage' %} {% if current_route == 'homepage' %}
{% set current_route = 'unread' %} {% set current_route = 'unread' %}
{% endif %} {% endif %}
<form name="form_mass_action" action="{{ path('mass_action', {redirect: current_path}) }}" method="post"> <form name="form_mass_action" action="{{ path('mass_action', {redirect: current_path}) }}" method="post" data-controller="batch-edit entries-navigation">
<div class="results"> <div class="results" data-entries-navigation-target="paginationWrapper">
<div class="nb-results"> <div class="nb-results">
{{ 'entry.list.number_on_the_page'|trans({'%count%': entries.count}) }} {{ 'entry.list.number_on_the_page'|trans({'%count%': entries.count}) }}
{% if entries.count > 0 %} {% if entries.count > 0 %}
<a class="results-item" href="{{ path('switch_view_mode', {redirect: current_path}) }}"><i class="material-icons">{% if list_mode == 0 %}view_list{% else %}view_module{% endif %}</i></a> <a class="results-item" href="{{ path('switch_view_mode', {redirect: current_path}) }}"><i class="material-icons">{% if list_mode == 0 %}view_list{% else %}view_module{% endif %}</i></a>
{% endif %} {% endif %}
{% if entries.count > 0 and is_granted('EDIT_ENTRIES') %} {% if entries.count > 0 and is_granted('EDIT_ENTRIES') %}
<label for="mass-action-inputs-displayed" class="mass-action-toggle results-item tooltipped" data-position="right" data-delay="50" data-tooltip="{{ 'entry.list.toggle_mass_action'|trans }}"><i class="material-icons">library_add_check</i></label> <label for="mass-action-inputs-displayed" class="mass-action-toggle results-item" data-controller="materialize--tooltip" data-position="right" data-delay="50" data-tooltip="{{ 'entry.list.toggle_mass_action'|trans }}"><i class="material-icons">library_add_check</i></label>
{% endif %} {% endif %}
{% if app.user.config.feedToken %} {% if app.user.config.feedToken %}
{% include "Entry/_feed_link.html.twig" %} {% include "Entry/_feed_link.html.twig" %}
@ -77,22 +77,22 @@
<input id="mass-action-inputs-displayed" class="toggle-checkbox" type="checkbox" /> <input id="mass-action-inputs-displayed" class="toggle-checkbox" type="checkbox" />
<div class="mass-action"> <div class="mass-action">
<div class="mass-action-group"> <div class="mass-action-group">
<input type="checkbox" class="entry-checkbox-input" data-toggle="[data-js='entry-checkbox']" data-js="checkboxes-toggle" /> <input type="checkbox" class="entry-checkbox-input" data-action="batch-edit#toggleSelection" />
<button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-read" title="{{ 'entry.list.toogle_as_read'|trans }}"><i class="material-icons">done</i></button> <button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-read" title="{{ 'entry.list.toogle_as_read'|trans }}"><i class="material-icons">done</i></button>
<button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-star" title="{{ 'entry.list.toogle_as_star'|trans }}" ><i class="material-icons">star</i></button> <button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-star" title="{{ 'entry.list.toogle_as_star'|trans }}" ><i class="material-icons">star</i></button>
<button class="mass-action-button btn cyan darken-1" type="submit" name="delete" onclick="return confirm('{{ 'entry.confirm.delete_entries'|trans|escape('js') }}')" title="{{ 'entry.list.delete'|trans }}"><i class="material-icons">delete</i></button> <button class="mass-action-button btn cyan darken-1" type="submit" name="delete" onclick="return confirm('{{ 'entry.confirm.delete_entries'|trans|escape('js') }}')" title="{{ 'entry.list.delete'|trans }}"><i class="material-icons">delete</i></button>
</div> </div>
<div class="mass-action-tags"> <div class="mass-action-tags">
<button class="btn cyan darken-1 mass-action-button mass-action-button--tags" type="submit" name="tag" title="{{ 'entry.list.add_tags'|trans }}"><i class="material-icons">label</i></button> <button class="btn cyan darken-1 mass-action-button mass-action-button--tags" type="submit" name="tag" title="{{ 'entry.list.add_tags'|trans }}" data-batch-edit-target="tagAction"><i class="material-icons">label</i></button>
<input type="text" class="mass-action-tags-input" name="tags" placeholder="{{ 'entry.list.mass_action_tags_input_placeholder'|trans }}" /> <input type="text" class="mass-action-tags-input" name="tags" placeholder="{{ 'entry.list.mass_action_tags_input_placeholder'|trans }}" data-action="keydown.enter->batch-edit#tagSelection:prevent:stop" />
</div> </div>
</div> </div>
<ol class="entries {% if list_mode == 1 %}collection{% else %}row entries-row data{% endif %}"> <ol class="entries {% if list_mode == 1 %}collection{% else %}row entries-row data{% endif %}">
{% for entry in entries %} {% for entry in entries %}
<li id="entry-{{ entry.id|e }}" class="{% if list_mode != 0 %}col collection-item{% endif %} s12" data-entry-id="{{ entry.id|e }}" data-test="entry"> <li id="entry-{{ entry.id|e }}" class="{% if list_mode != 0 %}col collection-item{% endif %} s12" data-entry-id="{{ entry.id|e }}" data-test="entry" data-entries-navigation-target="card">
{% if list_mode == 1 %} {% if list_mode == 1 %}
{% include "Entry/_card_list.html.twig" with {'entry': entry, 'currentRoute': current_route, 'routes': entries_with_archived_class_routes} only %} {% include "Entry/_card_list.html.twig" with {'entry': entry, 'currentRoute': current_route, 'routes': entries_with_archived_class_routes} only %}
{% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %} {% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %}
@ -114,7 +114,7 @@
<!-- Export --> <!-- Export -->
{% if has_exports and is_granted('EXPORT_ENTRIES') %} {% if has_exports and is_granted('EXPORT_ENTRIES') %}
<div id="export" class="sidenav" data-edge="right"> <div id="export" class="sidenav" data-controller="materialize--sidenav" data-materialize--sidenav-edge-value="right">
{% set current_tag = null %} {% set current_tag = null %}
{% if tag is defined %} {% if tag is defined %}
{% set current_tag = tag.slug %} {% set current_tag = tag.slug %}
@ -140,7 +140,7 @@
<!-- Filters --> <!-- Filters -->
{% if has_filters %} {% if has_filters %}
<div id="filters" class="sidenav" data-edge="right"> <div id="filters" class="sidenav" data-controller="materialize--sidenav" data-materialize--sidenav-edge-value="right">
<form action="{{ path('all') }}"> <form action="{{ path('all') }}">
<h4 class="center">{{ 'entry.filters.title'|trans }}</h4> <h4 class="center">{{ 'entry.filters.title'|trans }}</h4>

View file

@ -8,9 +8,9 @@
{% block menu %} {% block menu %}
<div class="progress"> <div class="progress">
<div class="determinate"></div> <div class="determinate" data-controller="scroll-indicator" data-action="scroll@window->scroll-indicator#updateWidth"></div>
</div> </div>
<nav class="hide-on-large-only js-entry-nav-top"> <nav class="hide-on-large-only" data-controller="sticky-nav" data-action="materialize--fab:click@window->sticky-nav#toggle">
<div class="nav-panel-item cyan darken-1"> <div class="nav-panel-item cyan darken-1">
<ul> <ul>
<li> <li>
@ -42,7 +42,7 @@
</ul> </ul>
</div> </div>
</nav> </nav>
<ul id="slide-out" class="left-bar collapsible sidenav sidenav-fixed reader-mode" data-collapsible="accordion"> <ul id="slide-out" class="left-bar collapsible sidenav sidenav-fixed reader-mode" data-controller="materialize--sidenav materialize--collapsible leftbar">
<li class="bold border-bottom hide-on-med-and-down"> <li class="bold border-bottom hide-on-med-and-down">
<a class="waves-effect collapsible-header" href="{{ path('homepage') }}"> <a class="waves-effect collapsible-header" href="{{ path('homepage') }}">
<i class="material-icons small">arrow_back</i> <i class="material-icons small">arrow_back</i>
@ -52,7 +52,7 @@
</li> </li>
<li class="bold border-bottom hide-on-med-and-down"> <li class="bold border-bottom hide-on-med-and-down">
<a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank" rel="noopener"> <a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank" rel="noopener" data-shortcuts-target="openOriginal">
<i class="material-icons small">link</i> <i class="material-icons small">link</i>
<span>{{ 'entry.view.left_menu.view_original_article'|trans }}</span> <span>{{ 'entry.view.left_menu.view_original_article'|trans }}</span>
</a> </a>
@ -76,7 +76,7 @@
{% if is_granted('ARCHIVE', entry) %} {% if is_granted('ARCHIVE', entry) %}
<li class="bold hide-on-med-and-down"> <li class="bold hide-on-med-and-down">
<a class="waves-effect collapsible-header markasread" title="{{ mark_as_read_label|trans }}" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}" id="markAsRead"> <a class="waves-effect collapsible-header markasread" title="{{ mark_as_read_label|trans }}" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}" id="markAsRead" data-shortcuts-target="markAsRead">
<i class="material-icons small">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i> <i class="material-icons small">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i>
<span>{{ mark_as_read_label|trans }}</span> <span>{{ mark_as_read_label|trans }}</span>
</a> </a>
@ -86,7 +86,7 @@
{% if is_granted('STAR', entry) %} {% if is_granted('STAR', entry) %}
<li class="bold hide-on-med-and-down"> <li class="bold hide-on-med-and-down">
<a class="waves-effect collapsible-header favorite" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}" id="setFav"> <a class="waves-effect collapsible-header favorite" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}" id="setFav" data-shortcuts-target="markAsFavorite">
<i class="material-icons small">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i> <i class="material-icons small">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i>
<span>{{ 'entry.view.left_menu.set_as_starred'|trans }}</span> <span>{{ 'entry.view.left_menu.set_as_starred'|trans }}</span>
</a> </a>
@ -96,7 +96,7 @@
{% if is_granted('DELETE', entry) %} {% if is_granted('DELETE', entry) %}
<li class="bold border-bottom"> <li class="bold border-bottom">
<a class="waves-effect collapsible-header delete" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}"> <a class="waves-effect collapsible-header delete" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}" data-shortcuts-target="deleteEntry">
<i class="material-icons small">delete</i> <i class="material-icons small">delete</i>
<span>{{ 'entry.view.left_menu.delete'|trans }}</span> <span>{{ 'entry.view.left_menu.delete'|trans }}</span>
</a> </a>
@ -105,7 +105,7 @@
{% endif %} {% endif %}
<li class="bold border-bottom"> <li class="bold border-bottom">
<a class="waves-effect collapsible-header" id="nav-btn-add-tag"> <a class="waves-effect collapsible-header" id="nav-btn-add-tag" data-action="click->materialize--sidenav#close click->leftbar#toggleAddTagForm">
<i class="material-icons small">label_outline</i> <i class="material-icons small">label_outline</i>
<span>{{ 'entry.view.left_menu.add_a_tag'|trans }}</span> <span>{{ 'entry.view.left_menu.add_a_tag'|trans }}</span>
</a> </a>
@ -119,19 +119,19 @@
</a> </a>
<ul class="collapsible-body"> <ul class="collapsible-body">
<li> <li>
<a href="#" class="js-theme-toggle" data-theme="light"> <a href="#" data-action="click->dark-theme#useLight:prevent">
<i class="theme-toggle-icon material-icons tiny">brightness_high</i> <i class="theme-toggle-icon material-icons tiny">brightness_high</i>
<span>{{ 'entry.view.left_menu.theme_toggle_light'|trans }}</span> <span>{{ 'entry.view.left_menu.theme_toggle_light'|trans }}</span>
</a> </a>
</li> </li>
<li> <li>
<a href="#" class="js-theme-toggle" data-theme="dark"> <a href="#" data-action="click->dark-theme#useDark:prevent">
<i class="theme-toggle-icon material-icons tiny">brightness_low</i> <i class="theme-toggle-icon material-icons tiny">brightness_low</i>
<span>{{ 'entry.view.left_menu.theme_toggle_dark'|trans }}</span> <span>{{ 'entry.view.left_menu.theme_toggle_dark'|trans }}</span>
</a> </a>
</li> </li>
<li> <li>
<a href="#" class="js-theme-toggle" data-theme="auto"> <a href="#" data-action="click->dark-theme#useAuto:prevent">
<i class="theme-toggle-icon material-icons tiny">brightness_auto</i> <i class="theme-toggle-icon material-icons tiny">brightness_auto</i>
<span>{{ 'entry.view.left_menu.theme_toggle_auto'|trans }}</span> <span>{{ 'entry.view.left_menu.theme_toggle_auto'|trans }}</span>
</a> </a>
@ -262,7 +262,7 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div id="article" class="article"> <div id="article" class="article" data-controller="scroll-storage" data-scroll-storage-entry-id-value="{{ entry.id }}" data-action="scroll@window->scroll-storage#saveScroll">
<header class="mbm"> <header class="mbm">
<h1> <h1>
<span{% if entry.language is defined and entry.language is not null %} lang="{{ entry.getHTMLLanguage() }}"{% endif %}>{{ entry.title|striptags|default('entry.default_title'|trans)|raw }}</span> <span{% if entry.language is defined and entry.language is not null %} lang="{{ entry.getHTMLLanguage() }}"{% endif %}>{{ entry.title|striptags|default('entry.default_title'|trans)|raw }}</span>
@ -320,17 +320,25 @@
</div> </div>
{% if is_granted('TAG', entry) %} {% if is_granted('TAG', entry) %}
<div class="input-field nav-panel-add-tag" style="display: none"> <div class="input-field nav-panel-add-tag hidden" data-controller="add-tag" data-action="leftbar:toggleAddTagForm@window->add-tag#toggle">
{{ render(controller('Wallabag\\Controller\\TagController::addTagFormAction', {'id': entry.id})) }} {{ render(controller('Wallabag\\Controller\\TagController::addTagFormAction', {'id': entry.id})) }}
</div> </div>
{% endif %} {% endif %}
</aside> </aside>
<article{% if entry.language is defined and entry.language is not null %} lang="{{ entry.getHTMLLanguage() }}"{% endif %}> <article
{% if entry.language is defined and entry.language is not null %} lang="{{ entry.getHTMLLanguage() }}"{% endif %}
data-controller="highlight annotations"
data-annotations-entry-id-value="{{ entry.id }}"
data-annotations-create-url-value="{{ path('annotations_post_annotation', {'entry': entry.id}) }}"
data-annotations-update-url-value="{{ path('annotations_put_annotation', {'annotation': 'idAnnotation'}) }}"
data-annotations-destroy-url-value="{{ path('annotations_delete_annotation', {'annotation': 'idAnnotation'}) }}"
data-annotations-search-url-value="{{ path('annotations_get_annotations', {'entry': entry.id}) }}"
>
{{ entry.content|raw }} {{ entry.content|raw }}
</article> </article>
<div class="fixed-action-btn js-fixed-action-btn horizontal click-to-toggle hide-on-large-only"> <div class="fixed-action-btn horizontal click-to-toggle hide-on-large-only" data-controller="materialize--fab" data-action="scroll@window->materialize--fab#autoDisplay click->materialize--fab#click">
<a class="btn-floating btn-large" data-toggle="actions"> <a class="btn-floating btn-large" data-toggle="actions">
<i class="material-icons">menu</i> <i class="material-icons">menu</i>
</a> </a>
@ -347,19 +355,6 @@
</ul> </ul>
</div> </div>
</div> </div>
<script id="annotationroutes" type="application/json">
{
"prefix": "",
"urls": {
"create": "{{ path('annotations_post_annotation', {'entry': entry.id}) }}",
"update": "{{ path('annotations_put_annotation', {'annotation': 'idAnnotation'}) }}",
"destroy": "{{ path('annotations_delete_annotation', {'annotation': 'idAnnotation'}) }}",
"search": "{{ path('annotations_get_annotations', {'entry': entry.id}) }}"
},
"entryId": "{{ entry.id }}"
}</script>
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View file

@ -1,4 +1,4 @@
<form class="input-field nav-panel-item nav-panel-add" style="display: none" name="entry" method="post" action="{{ path('new_entry') }}"> <form class="input-field nav-panel-item nav-panel-add" style="display: none" name="entry" method="post" action="{{ path('new_entry') }}" data-topbar-target="addUrl" data-action="topbar#submittingUrl">
{% if form_errors(form) %} {% if form_errors(form) %}
<span class="black-text">{{ form_errors(form) }}</span> <span class="black-text">{{ form_errors(form) }}</span>
{% endif %} {% endif %}
@ -8,8 +8,8 @@
<span class="black-text">{{ form_errors(form.url) }}</span> <span class="black-text">{{ form_errors(form.url) }}</span>
{% endif %} {% endif %}
{{ form_widget(form.url, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.new.placeholder'}}) }} {{ form_widget(form.url, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.new.placeholder', 'data-topbar-target': 'addUrlInput'}}) }}
<i class="material-icons close" aria-label="clear" role="button"></i> <i class="material-icons close" aria-label="clear" role="button" data-action="click->topbar#showActions" data-shortcuts-target="showActions"></i>
{{ form_rest(form) }} {{ form_rest(form) }}
</form> </form>

View file

@ -1,4 +1,4 @@
<form class="input-field nav-panel-item nav-panel-search" style="display: none" name="search" method="GET" action="{{ path('search') }}"> <form class="input-field nav-panel-item nav-panel-search" style="display: none" name="search" method="GET" action="{{ path('search') }}" data-topbar-target="search">
{% if form_errors(form) %} {% if form_errors(form) %}
<span class="black-text">{{ form_errors(form) }}</span> <span class="black-text">{{ form_errors(form) }}</span>
{% endif %} {% endif %}
@ -10,8 +10,8 @@
<input type="hidden" name="currentRoute" value="{{ currentRoute }}" /> <input type="hidden" name="currentRoute" value="{{ currentRoute }}" />
{{ form_widget(form.term, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.search.placeholder'}}) }} {{ form_widget(form.term, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.search.placeholder', 'data-topbar-target': 'searchInput'}}) }}
<i class="material-icons close" aria-label="clear" role="button"></i> <i class="material-icons close" aria-label="clear" role="button" data-action="click->topbar#showActions" data-shortcuts-target="showActions"></i>
{{ form_rest(form) }} {{ form_rest(form) }}
</form> </form>

View file

@ -1,9 +1,9 @@
{% if nbRedisMessages is defined and nbRedisMessages > 0 %} {% if nbRedisMessages is defined and nbRedisMessages > 0 %}
<p class="material-toast hidden">Messages in queue: {{ nbRedisMessages }}</p> <p class="hidden" data-controller="materialize--toast">Messages in queue: {{ nbRedisMessages }}</p>
{% endif %} {% endif %}
{% if nbRabbitMessages is defined and nbRabbitMessages > 0 %} {% if nbRabbitMessages is defined and nbRabbitMessages > 0 %}
<p class="material-toast hidden">Messages in queue: {{ nbRabbitMessages }}</p> <p class="hidden" data-controller="materialize--toast">Messages in queue: {{ nbRabbitMessages }}</p>
{% endif %} {% endif %}
{% if redisNotInstalled is defined and redisNotInstalled %} {% if redisNotInstalled is defined and redisNotInstalled %}

View file

@ -10,7 +10,7 @@
<div class="row"> <div class="row">
<div class="tabs-container col s12"> <div class="tabs-container col s12">
<ul class="tabs"> <ul class="tabs" data-controller="materialize--tabs">
<li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'about.top_menu.who_behind_wallabag'|trans }}</a></li> <li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'about.top_menu.who_behind_wallabag'|trans }}</a></li>
<li class="tab col s12 m6 l3"><a href="#set2">{{ 'about.top_menu.getting_help'|trans }}</a></li> <li class="tab col s12 m6 l3"><a href="#set2">{{ 'about.top_menu.getting_help'|trans }}</a></li>
<li class="tab col s12 m6 l3"><a href="#set3">{{ 'about.top_menu.helping'|trans }}</a></li> <li class="tab col s12 m6 l3"><a href="#set3">{{ 'about.top_menu.helping'|trans }}</a></li>

View file

@ -10,7 +10,7 @@
<div class="row"> <div class="row">
<div class="tabs-container col s12"> <div class="tabs-container col s12">
<ul class="tabs"> <ul class="tabs" data-controller="materialize--tabs">
<li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'howto.tab_menu.add_link'|trans }}</a></li> <li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'howto.tab_menu.add_link'|trans }}</a></li>
<li class="tab col s12 m6 l3"><a href="#set2">{{ 'howto.tab_menu.shortcuts'|trans }}</a></li> <li class="tab col s12 m6 l3"><a href="#set2">{{ 'howto.tab_menu.shortcuts'|trans }}</a></li>
</ul> </ul>

View file

@ -7,7 +7,7 @@
<span class="black-text">{{ form_errors(form.label) }}</span> <span class="black-text">{{ form_errors(form.label) }}</span>
{% endif %} {% endif %}
{{ form_widget(form.label, {'attr': {'autocomplete': 'off'}}) }} {{ form_widget(form.label, {'attr': {'autocomplete': 'off', 'data-add-tag-target': 'input'}}) }}
{{ form_widget(form.add, {'attr': {'class': 'btn waves-effect waves-light tags-add-form-submit'}}) }} {{ form_widget(form.add, {'attr': {'class': 'btn waves-effect waves-light tags-add-form-submit'}}) }}
{{ form_widget(form._token) }} {{ form_widget(form._token) }}

View file

@ -19,18 +19,19 @@
{% for tagWithNbEntries in allTagsWithNbEntries %} {% for tagWithNbEntries in allTagsWithNbEntries %}
{% set tag = tagWithNbEntries.tag %} {% set tag = tagWithNbEntries.tag %}
{% set nbEntries = tagWithNbEntries.nbEntries %} {% set nbEntries = tagWithNbEntries.nbEntries %}
<li title="{{ tag.label }} ({{ nbEntries }})" id="tag-{{ tag.id }}" class="chip"> <li title="{{ tag.label }} ({{ nbEntries }})" id="tag-{{ tag.id }}" class="chip" data-controller="tag">
<a href="{{ path('tag_entries', {'slug': tag.slug}) }}" class="card-tag-link" data-handle="tag-link"> <a href="{{ path('tag_entries', {'slug': tag.slug}) }}" class="card-tag-link" data-tag-target="link">
{{ tag.label }}&nbsp;({{ nbEntries }}) {{ tag.label }}&nbsp;({{ nbEntries }})
</a> </a>
{% if renameForms is defined and renameForms[tag.id] is defined and is_granted('EDIT', tag) %} {% if renameForms is defined and renameForms[tag.id] is defined and is_granted('EDIT', tag) %}
<form class="card-tag-form hidden" data-handle="tag-rename-form" action="{{ path('tag_rename', {'slug': tag.slug, redirect: current_path}) }}" method="POST"> <form class="card-tag-form hidden" data-tag-target="form" action="{{ path('tag_rename', {'slug': tag.slug, redirect: current_path}) }}" method="POST">
{{ form_widget(renameForms[tag.id].label, {'attr': {'value': tag.label}}) }} {{ form_widget(renameForms[tag.id].label, {'attr': {'value': tag.label, 'data-tag-target': 'input'}}) }}
{{ form_rest(renameForms[tag.id]) }} {{ form_rest(renameForms[tag.id]) }}
<button type="submit"><i class="material-icons">done</i></button>
</form> </form>
<a class="card-tag-icon card-tag-rename" data-handler="tag-rename" href="javascript:void(0);"> <button type="button" data-tag-target="edit" data-action="tag#showForm">
<i class="material-icons">mode_edit</i> <i class="material-icons">mode_edit</i>
</a> </button>
{% endif %} {% endif %}
{% if is_granted('DELETE', tag) %} {% if is_granted('DELETE', tag) %}
<a id="delete-{{ tag.slug }}" href="{{ path('tag_delete', {'slug': tag.slug, redirect: current_path}) }}" class="card-tag-icon card-tag-delete" onclick="return confirm('{{ 'tag.confirm.delete'|trans({'%name%': tag.label})|escape('js') }}')"> <a id="delete-{{ tag.slug }}" href="{{ path('tag_delete', {'slug': tag.slug, redirect: current_path}) }}" class="card-tag-icon card-tag-delete" onclick="return confirm('{{ 'tag.confirm.delete'|trans({'%name%': tag.label})|escape('js') }}')">

View file

@ -48,16 +48,16 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row" data-controller="fake-radio">
<div class="input-field col s12"> <div class="input-field col s12">
<label for="{{ edit_form.emailTwoFactor.vars.id }}"> <label for="{{ edit_form.emailTwoFactor.vars.id }}">
{{ form_widget(edit_form.emailTwoFactor) }} {{ form_widget(edit_form.emailTwoFactor, {attr: {'data-fake-radio-target': 'emailTwoFactor', 'data-action': 'fake-radio#uncheckGoogle'}}) }}
<span>{{ edit_form.emailTwoFactor.vars.label|trans }}</span> <span>{{ edit_form.emailTwoFactor.vars.label|trans }}</span>
</label> </label>
</div> </div>
<div class="input-field col s12"> <div class="input-field col s12">
<label for="{{ edit_form.googleTwoFactor.vars.id }}"> <label for="{{ edit_form.googleTwoFactor.vars.id }}">
{{ form_widget(edit_form.googleTwoFactor) }} {{ form_widget(edit_form.googleTwoFactor, {attr: {'data-fake-radio-target': 'googleTwoFactor', 'data-action': 'fake-radio#uncheckEmail'}}) }}
<span>{{ edit_form.googleTwoFactor.vars.label|trans }}</span> <span>{{ edit_form.googleTwoFactor.vars.label|trans }}</span>
</label> </label>
</div> </div>

View file

@ -4,7 +4,7 @@
<!--[if lte IE 7]><html class="no-js ie7 ie67 ie678"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]--> <!--[if lte IE 7]><html class="no-js ie7 ie67 ie678"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]-->
<!--[if IE 8]><html class="no-js ie8 ie678"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]--> <!--[if IE 8]><html class="no-js ie8 ie678"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]-->
<!--[if gt IE 8]><html class="no-js"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]--> <!--[if gt IE 8]><html class="no-js"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]-->
<html{% if lang is not empty %} class="{{ theme_class() }}" lang="{{ lang }}"{% endif %}> <html{% if lang is not empty %} lang="{{ lang }}"{% endif %} class="{{ theme_class() }}" data-controller="dark-theme shortcuts" data-shortcuts-entries-navigation-outlet="[data-controller~='entries-navigation']">
<head> <head>
{% block head %} {% block head %}
<meta name="viewport" content="initial-scale=1.0"> <meta name="viewport" content="initial-scale=1.0">

View file

@ -11,7 +11,7 @@
<div class="row"> <div class="row">
<div class="div_tabs col s12"> <div class="div_tabs col s12">
<ul class="tabs"> <ul class="tabs" data-controller="materialize--tabs">
{% for section in sections|craue_sortSections %} {% for section in sections|craue_sortSections %}
<li class="tab col s12 m6 l3"><a href="#set-{{ section }}">{{ section|trans({}, 'CraueConfigBundle') }}</a></li> <li class="tab col s12 m6 l3"><a href="#set-{{ section }}">{{ section|trans({}, 'CraueConfigBundle') }}</a></li>
{% endfor %} {% endfor %}

View file

@ -5,11 +5,11 @@
<div class="card-content"> <div class="card-content">
{% if error %} {% if error %}
<p class="material-toast hidden">{{ error.messageKey|trans(error.messageData, 'security') }}</p> <p class="hidden" data-controller="materialize--toast">{{ error.messageKey|trans(error.messageData, 'security') }}</p>
{% endif %} {% endif %}
{% for flash_message in app.session.flashbag.get('notice') %} {% for flash_message in app.session.flashbag.get('notice') %}
<p class="material-toast hidden">{{ flash_message }}</p> <p class="hidden" data-controller="materialize--toast">{{ flash_message }}</p>
{% endfor %} {% endfor %}
<div class="row"> <div class="row">

View file

@ -35,7 +35,7 @@
{% block messages %} {% block messages %}
{% for flash_message in app.session.flashbag.get('notice') %} {% for flash_message in app.session.flashbag.get('notice') %}
<p class="material-toast hidden">{{ flash_message|trans }}</p> <p class="hidden" data-controller="materialize--toast">{{ flash_message|trans }}</p>
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}
@ -43,7 +43,7 @@
{% block menu %} {% block menu %}
<nav class="cyan darken-1"> <nav class="cyan darken-1">
<ul id="slide-out" class="left-bar sidenav sidenav-fixed"> <ul id="slide-out" class="left-bar sidenav sidenav-fixed" data-controller="materialize--sidenav">
{% block logo %} {% block logo %}
<li class="logo border-bottom"> <li class="logo border-bottom">
{% if is_granted('LIST_ENTRIES') %} {% if is_granted('LIST_ENTRIES') %}
@ -79,8 +79,8 @@
</li> </li>
{% endif %} {% endif %}
</ul> </ul>
<div class="nav-panels"> <div class="nav-panels" data-controller="topbar">
<div class="nav-panel-actions nav-panel-item"> <div class="nav-panel-actions nav-panel-item" data-topbar-target="actions">
<div class="nav-panel-top"> <div class="nav-panel-top">
<a href="#" data-target="slide-out" class="nav-panel-menu sidenav-trigger"><i class="material-icons">menu</i></a> <a href="#" data-target="slide-out" class="nav-panel-menu sidenav-trigger"><i class="material-icons">menu</i></a>
<h1 class="left action"> <h1 class="left action">
@ -90,18 +90,18 @@
</div> </div>
<ul class="input-field nav-panel-buttom"> <ul class="input-field nav-panel-buttom">
<li class="bold toggle-add-url-container"> <li class="bold toggle-add-url-container">
<a class="waves-effect tooltipped toggle-add-url" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.add_new_entry'|trans }}" href="{{ path('new') }}" id="nav-btn-add"> <a class="waves-effect toggle-add-url" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.add_new_entry'|trans }}" href="{{ path('new') }}" data-action="topbar#showAddUrl:prevent:stop" data-shortcuts-target="showAddUrl">
<i class="material-icons">add</i> <i class="material-icons">add</i>
</a> </a>
</li> </li>
<li> <li>
<a class="waves-effect tooltipped" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.search'|trans }}" href="javascript: void(null);" id="nav-btn-search"> <a class="waves-effect" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.search'|trans }}" href="javascript: void(null);" data-action="topbar#showSearch:prevent:stop" data-shortcuts-target="showSearch">
<i class="material-icons">search</i> <i class="material-icons">search</i>
</a> </a>
</li> </li>
{% block nav_panel_extra_actions '' %} {% block nav_panel_extra_actions '' %}
<li class="bold"> <li class="bold">
<a class="wave-effect tooltipped dropdown-trigger" data-covertrigger="false" data-constrainwidth="false" data-target="dropdown-account" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.account'|trans }}" href="#" id="news_menu"> <a class="wave-effect dropdown-trigger" data-controller="materialize--dropdown materialize--tooltip" data-target="dropdown-account" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.account'|trans }}" href="#" id="news_menu">
<i class="material-icons" id="news_link">account_circle</i> <i class="material-icons" id="news_link">account_circle</i>
</a> </a>
</li> </li>
@ -134,19 +134,19 @@
<li class="divider"></li> <li class="divider"></li>
{% endif %} {% endif %}
<li> <li>
<a href="#" class="js-theme-toggle" data-theme="light"> <a href="#" data-action="click->dark-theme#useLight:prevent">
<i class="theme-toggle-icon material-icons tiny">brightness_high</i> <i class="theme-toggle-icon material-icons tiny">brightness_high</i>
<span>{{ 'menu.left.theme_toggle_light'|trans }}</span> <span>{{ 'menu.left.theme_toggle_light'|trans }}</span>
</a> </a>
</li> </li>
<li> <li>
<a href="#" class="js-theme-toggle" data-theme="dark"> <a href="#" data-action="click->dark-theme#useDark:prevent">
<i class="theme-toggle-icon material-icons tiny">brightness_low</i> <i class="theme-toggle-icon material-icons tiny">brightness_low</i>
<span>{{ 'menu.left.theme_toggle_dark'|trans }}</span> <span>{{ 'menu.left.theme_toggle_dark'|trans }}</span>
</a> </a>
</li> </li>
<li> <li>
<a href="#" class="js-theme-toggle" data-theme="auto"> <a href="#" data-action="click->dark-theme#useAuto:prevent">
<i class="theme-toggle-icon material-icons tiny">brightness_auto</i> <i class="theme-toggle-icon material-icons tiny">brightness_auto</i>
<span>{{ 'menu.left.theme_toggle_auto'|trans }}</span> <span>{{ 'menu.left.theme_toggle_auto'|trans }}</span>
</a> </a>

View file

@ -10,6 +10,7 @@ Encore
.addEntry('main', './assets/index.js') .addEntry('main', './assets/index.js')
.addEntry('public', './assets/share.js') .addEntry('public', './assets/share.js')
.splitEntryChunks() .splitEntryChunks()
.enableStimulusBridge('./assets/controllers.json')
.enableSingleRuntimeChunk() .enableSingleRuntimeChunk()
.cleanupOutputBeforeBuild() .cleanupOutputBeforeBuild()
.enableBuildNotifications() .enableBuildNotifications()
@ -21,7 +22,6 @@ Encore
config.corejs = '3.23'; config.corejs = '3.23';
}) })
.enableSassLoader() .enableSassLoader()
.enablePostCssLoader() .enablePostCssLoader();
.autoProvidejQuery();
module.exports = Encore.getWebpackConfig(); module.exports = Encore.getWebpackConfig();

View file

@ -911,6 +911,16 @@
resolved "https://registry.yarnpkg.com/@fontsource/oswald/-/oswald-5.2.5.tgz#01ef5b61fae44542eb22330255d32b728ee45b0c" resolved "https://registry.yarnpkg.com/@fontsource/oswald/-/oswald-5.2.5.tgz#01ef5b61fae44542eb22330255d32b728ee45b0c"
integrity sha512-Sw8ayEYCoOzG2ISw5HaX3d5ILt3OEG2VFX2nzHaGywYD9p0WvVfO4SBK5/y9JGuOty3jA6OhptxOYZgwjTTPLQ== integrity sha512-Sw8ayEYCoOzG2ISw5HaX3d5ILt3OEG2VFX2nzHaGywYD9p0WvVfO4SBK5/y9JGuOty3jA6OhptxOYZgwjTTPLQ==
"@hotwired/stimulus-webpack-helpers@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz#4cd74487adeca576c9865ac2b9fe5cb20cef16dd"
integrity sha512-wa/zupVG0eWxRYJjC1IiPBdt3Lruv0RqGN+/DTMmUWUyMAEB27KXmVY6a8YpUVTM7QwVuaLNGW4EqDgrS2upXQ==
"@hotwired/stimulus@^3.2.2":
version "3.2.2"
resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.2.2.tgz#071aab59c600fed95b97939e605ff261a4251608"
integrity sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==
"@humanwhocodes/config-array@^0.13.0": "@humanwhocodes/config-array@^0.13.0":
version "0.13.0" version "0.13.0"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748"
@ -1056,6 +1066,16 @@
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==
"@symfony/stimulus-bridge@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@symfony/stimulus-bridge/-/stimulus-bridge-4.0.0.tgz#dbd352a373f8ff323f2895e0bb29f22b9abcc122"
integrity sha512-BfeXHAyNtE2hFJtTKFS8vLW2ElqNyzUZJJ4TMeUhrjBjYVt4/myeQxpLidy995l+TEzryE7YrnShqLviBr3pAg==
dependencies:
"@hotwired/stimulus-webpack-helpers" "^1.0.1"
"@types/webpack-env" "^1.16.4"
loader-utils "^2.0.0 || ^3.0.0"
schema-utils "^3.0.0 || ^4.0.0"
"@symfony/webpack-encore@^5.1.0": "@symfony/webpack-encore@^5.1.0":
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/@symfony/webpack-encore/-/webpack-encore-5.1.0.tgz#d5664153136959e3baf3e248c9b55350c2c81a6d" resolved "https://registry.yarnpkg.com/@symfony/webpack-encore/-/webpack-encore-5.1.0.tgz#d5664153136959e3baf3e248c9b55350c2c81a6d"
@ -1149,6 +1169,11 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"
integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==
"@types/webpack-env@^1.16.4":
version "1.18.8"
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.8.tgz#71f083718c094204d7b64443701d32f1db3989e3"
integrity sha512-G9eAoJRMLjcvN4I08wB5I7YofOb/kaJNd5uoCMX+LbKXTPCF+ZIHuqTnFaK9Jz1rgs035f9JUPUhNFtqgucy/A==
"@types/yargs-parser@*": "@types/yargs-parser@*":
version "21.0.3" version "21.0.3"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
@ -1371,7 +1396,6 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.9.0:
annotator@wallabag/annotator#master: annotator@wallabag/annotator#master:
version "2.0.0-alpha.4" version "2.0.0-alpha.4"
uid "082069d777ed0fe5080392e85675ef3a519c7886"
resolved "https://codeload.github.com/wallabag/annotator/tar.gz/082069d777ed0fe5080392e85675ef3a519c7886" resolved "https://codeload.github.com/wallabag/annotator/tar.gz/082069d777ed0fe5080392e85675ef3a519c7886"
dependencies: dependencies:
backbone-extend-standalone "^0.1.2" backbone-extend-standalone "^0.1.2"
@ -3353,11 +3377,6 @@ jiti@^1.20.0:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
jquery.cookie@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jquery.cookie/-/jquery.cookie-1.4.1.tgz#d63dce209eab691fe63316db08ca9e47e0f9385b"
integrity sha512-c/hZOOL+8VSw/FkTVH637gS1/6YzMSCROpTZ2qBYwJ7s7sHajU7uBkSSiE5+GXWwrfCCyO+jsYjUQ7Hs2rIxAA==
jquery@^3.7.1: jquery@^3.7.1:
version "3.7.1" version "3.7.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
@ -3481,6 +3500,11 @@ loader-utils@^2.0.0:
emojis-list "^3.0.0" emojis-list "^3.0.0"
json5 "^2.1.2" json5 "^2.1.2"
"loader-utils@^2.0.0 || ^3.0.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5"
integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==
locate-path@^5.0.0: locate-path@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
@ -4680,7 +4704,7 @@ schema-utils@^3.0.0:
ajv "^6.12.5" ajv "^6.12.5"
ajv-keywords "^3.5.2" ajv-keywords "^3.5.2"
schema-utils@^4.0.0, schema-utils@^4.2.0, schema-utils@^4.3.0: "schema-utils@^3.0.0 || ^4.0.0", schema-utils@^4.0.0, schema-utils@^4.2.0, schema-utils@^4.3.0:
version "4.3.0" version "4.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.0.tgz#3b669f04f71ff2dfb5aba7ce2d5a9d79b35622c0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.0.tgz#3b669f04f71ff2dfb5aba7ce2d5a9d79b35622c0"
integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g== integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==