mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-25 09:42:10 +08:00
ESLINT: Addressed remaining detected issues
This commit is contained in:
parent
0519e58fbf
commit
da3ae3ba8b
1
package-lock.json
generated
1
package-lock.json
generated
|
@ -18,6 +18,7 @@
|
|||
"@codemirror/state": "^6.2.0",
|
||||
"@codemirror/theme-one-dark": "^6.1.1",
|
||||
"@codemirror/view": "^6.9.4",
|
||||
"@lezer/highlight": "^1.1.4",
|
||||
"@ssddanbrown/codemirror-lang-smarty": "^1.0.0",
|
||||
"@ssddanbrown/codemirror-lang-twig": "^1.0.0",
|
||||
"codemirror": "^6.0.1",
|
||||
|
|
90
package.json
90
package.json
|
@ -42,6 +42,7 @@
|
|||
"@codemirror/state": "^6.2.0",
|
||||
"@codemirror/theme-one-dark": "^6.1.1",
|
||||
"@codemirror/view": "^6.9.4",
|
||||
"@lezer/highlight": "^1.1.4",
|
||||
"@ssddanbrown/codemirror-lang-smarty": "^1.0.0",
|
||||
"@ssddanbrown/codemirror-lang-twig": "^1.0.0",
|
||||
"codemirror": "^6.0.1",
|
||||
|
@ -58,48 +59,77 @@
|
|||
"es2021": true
|
||||
},
|
||||
"extends": "airbnb-base",
|
||||
"ignorePatterns": ["resources/**/*-stub.js"],
|
||||
"overrides": [
|
||||
"ignorePatterns": [
|
||||
"resources/**/*-stub.js"
|
||||
],
|
||||
"overrides": [],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"indent": ["error", 4],
|
||||
"arrow-parens": ["error", "as-needed"],
|
||||
"padded-blocks": ["error", {
|
||||
"indent": [
|
||||
"error",
|
||||
4
|
||||
],
|
||||
"arrow-parens": [
|
||||
"error",
|
||||
"as-needed"
|
||||
],
|
||||
"padded-blocks": [
|
||||
"error",
|
||||
{
|
||||
"blocks": "never",
|
||||
"classes": "always"
|
||||
}],
|
||||
"object-curly-spacing": ["error", "never"],
|
||||
"space-before-function-paren": ["error", {
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}],
|
||||
}
|
||||
],
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"space-before-function-paren": [
|
||||
"error",
|
||||
{
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}
|
||||
],
|
||||
"import/prefer-default-export": "off",
|
||||
"no-plusplus": ["error", {
|
||||
"allowForLoopAfterthoughts": true
|
||||
}],
|
||||
"no-plusplus": [
|
||||
"error",
|
||||
{
|
||||
"allowForLoopAfterthoughts": true
|
||||
}
|
||||
],
|
||||
"arrow-body-style": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
"no-continue": "off",
|
||||
"no-console": ["warn", {
|
||||
"allow": ["error"]
|
||||
}],
|
||||
"max-len": ["error", {
|
||||
"code": 110,
|
||||
"tabWidth": 4,
|
||||
"ignoreUrls": true,
|
||||
"ignoreComments": false,
|
||||
"ignoreRegExpLiterals": true,
|
||||
"ignoreStrings": true,
|
||||
"ignoreTemplateLiterals": true
|
||||
}],
|
||||
"no-param-reassign": ["error", {
|
||||
"props": false
|
||||
}]
|
||||
"prefer-destructuring": "off",
|
||||
"class-methods-use-this": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-console": [
|
||||
"warn",
|
||||
{
|
||||
"allow": [
|
||||
"error",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-new": "off",
|
||||
"max-len": [
|
||||
"error",
|
||||
{
|
||||
"code": 110,
|
||||
"tabWidth": 4,
|
||||
"ignoreUrls": true,
|
||||
"ignoreComments": false,
|
||||
"ignoreRegExpLiterals": true,
|
||||
"ignoreStrings": true,
|
||||
"ignoreTemplateLiterals": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import events from './services/events';
|
||||
import * as events from './services/events';
|
||||
import * as httpInstance from './services/http';
|
||||
import Translations from './services/translations';
|
||||
|
||||
|
|
|
@ -6,24 +6,36 @@ import {createView} from './views';
|
|||
import {SimpleEditorInterface} from './simple-editor-interface';
|
||||
|
||||
/**
|
||||
* Highlight pre elements on a page
|
||||
* Add a button to a CodeMirror instance which copies the contents to the clipboard upon click.
|
||||
* @param {EditorView} editorView
|
||||
*/
|
||||
export function highlight() {
|
||||
const codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre');
|
||||
for (const codeBlock of codeBlocks) {
|
||||
highlightElem(codeBlock);
|
||||
}
|
||||
}
|
||||
function addCopyIcon(editorView) {
|
||||
const copyIcon = '<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>';
|
||||
const checkIcon = '<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>';
|
||||
const copyButton = document.createElement('button');
|
||||
copyButton.setAttribute('type', 'button');
|
||||
copyButton.classList.add('cm-copy-button');
|
||||
copyButton.innerHTML = copyIcon;
|
||||
editorView.dom.appendChild(copyButton);
|
||||
|
||||
/**
|
||||
* Highlight all code blocks within the given parent element
|
||||
* @param {HTMLElement} parent
|
||||
*/
|
||||
export function highlightWithin(parent) {
|
||||
const codeBlocks = parent.querySelectorAll('pre');
|
||||
for (const codeBlock of codeBlocks) {
|
||||
highlightElem(codeBlock);
|
||||
}
|
||||
const notifyTime = 620;
|
||||
const transitionTime = 60;
|
||||
copyButton.addEventListener('click', () => {
|
||||
copyTextToClipboard(editorView.state.doc.toString());
|
||||
copyButton.classList.add('success');
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.innerHTML = checkIcon;
|
||||
}, transitionTime / 2);
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.classList.remove('success');
|
||||
}, notifyTime);
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.innerHTML = copyIcon;
|
||||
}, notifyTime + (transitionTime / 2));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,7 +44,7 @@ export function highlightWithin(parent) {
|
|||
*/
|
||||
function highlightElem(elem) {
|
||||
const innerCodeElem = elem.querySelector('code[class^=language-]');
|
||||
elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi, '\n');
|
||||
elem.innerHTML = elem.innerHTML.replace(/<br\s*\/?>/gi, '\n');
|
||||
const content = elem.textContent.trimEnd();
|
||||
|
||||
let langName = '';
|
||||
|
@ -57,36 +69,24 @@ function highlightElem(elem) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a button to a CodeMirror instance which copies the contents to the clipboard upon click.
|
||||
* @param {EditorView} editorView
|
||||
* Highlight all code blocks within the given parent element
|
||||
* @param {HTMLElement} parent
|
||||
*/
|
||||
function addCopyIcon(editorView) {
|
||||
const copyIcon = '<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>';
|
||||
const checkIcon = '<svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>';
|
||||
const copyButton = document.createElement('button');
|
||||
copyButton.setAttribute('type', 'button');
|
||||
copyButton.classList.add('cm-copy-button');
|
||||
copyButton.innerHTML = copyIcon;
|
||||
editorView.dom.appendChild(copyButton);
|
||||
export function highlightWithin(parent) {
|
||||
const codeBlocks = parent.querySelectorAll('pre');
|
||||
for (const codeBlock of codeBlocks) {
|
||||
highlightElem(codeBlock);
|
||||
}
|
||||
}
|
||||
|
||||
const notifyTime = 620;
|
||||
const transitionTime = 60;
|
||||
copyButton.addEventListener('click', event => {
|
||||
copyTextToClipboard(editorView.state.doc.toString());
|
||||
copyButton.classList.add('success');
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.innerHTML = checkIcon;
|
||||
}, transitionTime / 2);
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.classList.remove('success');
|
||||
}, notifyTime);
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.innerHTML = copyIcon;
|
||||
}, notifyTime + (transitionTime / 2));
|
||||
});
|
||||
/**
|
||||
* Highlight pre elements on a page
|
||||
*/
|
||||
export function highlight() {
|
||||
const codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre');
|
||||
for (const codeBlock of codeBlocks) {
|
||||
highlightElem(codeBlock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,7 @@ export class AjaxDeleteRow extends Component {
|
|||
window.$events.emit('success', resp.data.message);
|
||||
}
|
||||
this.row.remove();
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
this.row.style.opacity = null;
|
||||
this.row.style.pointerEvents = null;
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ export class Attachments extends Component {
|
|||
this.startEdit(event.detail.id);
|
||||
});
|
||||
|
||||
this.container.addEventListener('event-emit-select-edit-back', event => {
|
||||
this.container.addEventListener('event-emit-select-edit-back', () => {
|
||||
this.stopEdit();
|
||||
});
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ export class AutoSuggest extends Component {
|
|||
setupListeners() {
|
||||
const navHandler = new KeyboardNavigationHandler(
|
||||
this.list,
|
||||
event => {
|
||||
() => {
|
||||
this.input.focus();
|
||||
setTimeout(() => this.hideSuggestions(), 1);
|
||||
},
|
||||
|
@ -104,7 +104,8 @@ export class AutoSuggest extends Component {
|
|||
*/
|
||||
displaySuggestions(suggestions) {
|
||||
if (suggestions.length === 0) {
|
||||
return this.hideSuggestions();
|
||||
this.hideSuggestions();
|
||||
return;
|
||||
}
|
||||
|
||||
// This used to use <button>s but was changed to div elements since Safari would not focus on buttons
|
||||
|
|
|
@ -45,19 +45,19 @@ const sortOperations = {
|
|||
*/
|
||||
const moveActions = {
|
||||
up: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return !(elem.previousElementSibling === null && !parent);
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
run(elem, parent) {
|
||||
const newSibling = elem.previousElementSibling || parent;
|
||||
newSibling.insertAdjacentElement('beforebegin', elem);
|
||||
},
|
||||
},
|
||||
down: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return !(elem.nextElementSibling === null && !parent);
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
run(elem, parent) {
|
||||
const newSibling = elem.nextElementSibling || parent;
|
||||
newSibling.insertAdjacentElement('afterend', elem);
|
||||
},
|
||||
|
@ -81,10 +81,10 @@ const moveActions = {
|
|||
},
|
||||
},
|
||||
next_chapter: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return elem.dataset.type === 'page' && this.getNextChapter(elem, parent);
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
run(elem, parent) {
|
||||
const nextChapter = this.getNextChapter(elem, parent);
|
||||
nextChapter.querySelector('ul').prepend(elem);
|
||||
},
|
||||
|
@ -92,14 +92,14 @@ const moveActions = {
|
|||
const topLevel = (parent || elem);
|
||||
const topItems = Array.from(topLevel.parentElement.children);
|
||||
const index = topItems.indexOf(topLevel);
|
||||
return topItems.slice(index + 1).find(elem => elem.dataset.type === 'chapter');
|
||||
return topItems.slice(index + 1).find(item => item.dataset.type === 'chapter');
|
||||
},
|
||||
},
|
||||
prev_chapter: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return elem.dataset.type === 'page' && this.getPrevChapter(elem, parent);
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
run(elem, parent) {
|
||||
const prevChapter = this.getPrevChapter(elem, parent);
|
||||
prevChapter.querySelector('ul').append(elem);
|
||||
},
|
||||
|
@ -107,11 +107,11 @@ const moveActions = {
|
|||
const topLevel = (parent || elem);
|
||||
const topItems = Array.from(topLevel.parentElement.children);
|
||||
const index = topItems.indexOf(topLevel);
|
||||
return topItems.slice(0, index).reverse().find(elem => elem.dataset.type === 'chapter');
|
||||
return topItems.slice(0, index).reverse().find(item => item.dataset.type === 'chapter');
|
||||
},
|
||||
},
|
||||
book_end: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return parent || (parent === null && elem.nextElementSibling);
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
|
@ -119,7 +119,7 @@ const moveActions = {
|
|||
},
|
||||
},
|
||||
book_start: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return parent || (parent === null && elem.previousElementSibling);
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
|
@ -127,18 +127,18 @@ const moveActions = {
|
|||
},
|
||||
},
|
||||
before_chapter: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return parent;
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
run(elem, parent) {
|
||||
parent.insertAdjacentElement('beforebegin', elem);
|
||||
},
|
||||
},
|
||||
after_chapter: {
|
||||
active(elem, parent, book) {
|
||||
active(elem, parent) {
|
||||
return parent;
|
||||
},
|
||||
run(elem, parent, book) {
|
||||
run(elem, parent) {
|
||||
parent.insertAdjacentElement('afterend', elem);
|
||||
},
|
||||
},
|
||||
|
@ -196,7 +196,7 @@ export class BookSort extends Component {
|
|||
reverse = (lastSort === sort) ? !reverse : false;
|
||||
let sortFunction = sortOperations[sort];
|
||||
if (reverse && reversibleTypes.includes(sort)) {
|
||||
sortFunction = function(a, b) {
|
||||
sortFunction = function reverseSortOperation(a, b) {
|
||||
return 0 - sortOperations[sort](a, b);
|
||||
};
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ export class BookSort extends Component {
|
|||
animation: 150,
|
||||
fallbackOnBody: true,
|
||||
swapThreshold: 0.65,
|
||||
onSort: event => {
|
||||
onSort: () => {
|
||||
this.ensureNoNestedChapters();
|
||||
this.updateMapInput();
|
||||
this.updateMoveActionStateForAll();
|
||||
|
|
|
@ -27,7 +27,11 @@ export class ChapterContents extends Component {
|
|||
|
||||
click(event) {
|
||||
event.preventDefault();
|
||||
this.isOpen ? this.close() : this.open();
|
||||
if (this.isOpen) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,9 +43,9 @@ export class CodeEditor extends Component {
|
|||
this.languageInputChange(language);
|
||||
});
|
||||
|
||||
onEnterPress(this.languageInput, e => this.save());
|
||||
this.languageInput.addEventListener('input', e => this.languageInputChange(this.languageInput.value));
|
||||
onSelect(this.saveButton, e => this.save());
|
||||
onEnterPress(this.languageInput, () => this.save());
|
||||
this.languageInput.addEventListener('input', () => this.languageInputChange(this.languageInput.value));
|
||||
onSelect(this.saveButton, () => this.save());
|
||||
|
||||
onChildEvent(this.historyList, 'button', 'click', (event, elem) => {
|
||||
event.preventDefault();
|
||||
|
@ -74,7 +74,8 @@ export class CodeEditor extends Component {
|
|||
|
||||
onChildEvent(button.parentElement, '.lang-option-favorite-toggle', 'click', () => {
|
||||
isFavorite = !isFavorite;
|
||||
isFavorite ? this.favourites.add(language) : this.favourites.delete(language);
|
||||
const action = isFavorite ? this.favourites.add : this.favourites.delete;
|
||||
action(language);
|
||||
button.setAttribute('data-favourite', isFavorite ? 'true' : 'false');
|
||||
|
||||
window.$http.patch('/preferences/update-code-language-favourite', {
|
||||
|
@ -173,7 +174,7 @@ export class CodeEditor extends Component {
|
|||
const historyKeys = Object.keys(this.history).reverse();
|
||||
this.historyDropDown.classList.toggle('hidden', historyKeys.length === 0);
|
||||
this.historyList.innerHTML = historyKeys.map(key => {
|
||||
const localTime = (new Date(parseInt(key))).toLocaleTimeString();
|
||||
const localTime = (new Date(parseInt(key, 10))).toLocaleTimeString();
|
||||
return `<li><button type="button" data-time="${key}" class="text-item">${localTime}</button></li>`;
|
||||
}).join('');
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ export class ConfirmDialog extends Component {
|
|||
this.sendResult(false);
|
||||
});
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
return new Promise(res => {
|
||||
this.res = res;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -41,7 +41,11 @@ export class Dropdown extends Component {
|
|||
this.menu.style.position = 'fixed';
|
||||
this.menu.style.width = `${menuOriginalRect.width}px`;
|
||||
this.menu.style.left = `${menuOriginalRect.left}px`;
|
||||
heightOffset = dropUpwards ? (window.innerHeight - menuOriginalRect.top - toggleHeight / 2) : menuOriginalRect.top;
|
||||
if (dropUpwards) {
|
||||
heightOffset = (window.innerHeight - menuOriginalRect.top - toggleHeight / 2);
|
||||
} else {
|
||||
heightOffset = menuOriginalRect.top;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust menu to display upwards if near the bottom of the screen
|
||||
|
@ -55,8 +59,8 @@ export class Dropdown extends Component {
|
|||
|
||||
// Set listener to hide on mouse leave or window click
|
||||
this.menu.addEventListener('mouseleave', this.hide);
|
||||
window.addEventListener('click', event => {
|
||||
if (!this.menu.contains(event.target)) {
|
||||
window.addEventListener('click', clickEvent => {
|
||||
if (!this.menu.contains(clickEvent.target)) {
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ export class Dropzone extends Component {
|
|||
this.uploadLimitMessage = this.$opts.uploadLimitMessage;
|
||||
this.timeoutMessage = this.$opts.timeoutMessage;
|
||||
|
||||
const _this = this;
|
||||
const component = this;
|
||||
this.dz = new DropZoneLib(this.container, {
|
||||
addRemoveLinks: true,
|
||||
dictRemoveFile: this.removeMessage,
|
||||
|
@ -23,9 +23,9 @@ export class Dropzone extends Component {
|
|||
withCredentials: true,
|
||||
init() {
|
||||
this.dz = this;
|
||||
this.dz.on('sending', _this.onSending.bind(_this));
|
||||
this.dz.on('success', _this.onSuccess.bind(_this));
|
||||
this.dz.on('error', _this.onError.bind(_this));
|
||||
this.dz.on('sending', component.onSending.bind(component));
|
||||
this.dz.on('success', component.onSuccess.bind(component));
|
||||
this.dz.on('error', component.onError.bind(component));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ export class Dropzone extends Component {
|
|||
const token = window.document.querySelector('meta[name=token]').getAttribute('content');
|
||||
data.append('_token', token);
|
||||
|
||||
xhr.ontimeout = e => {
|
||||
xhr.ontimeout = () => {
|
||||
this.dz.emit('complete', file);
|
||||
this.dz.emit('error', file, this.timeoutMessage);
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ export class EntityPermissions extends Component {
|
|||
});
|
||||
|
||||
// Role select change
|
||||
this.roleSelect.addEventListener('change', event => {
|
||||
this.roleSelect.addEventListener('change', () => {
|
||||
const roleId = this.roleSelect.value;
|
||||
if (roleId) {
|
||||
this.addRoleRow(roleId);
|
||||
|
|
|
@ -31,7 +31,8 @@ export class EntitySearch extends Component {
|
|||
runSearch() {
|
||||
const term = this.searchInput.value.trim();
|
||||
if (term.length === 0) {
|
||||
return this.clearSearch();
|
||||
this.clearSearch();
|
||||
return;
|
||||
}
|
||||
|
||||
this.searchView.classList.remove('hidden');
|
||||
|
|
|
@ -29,7 +29,7 @@ export class EntitySelector extends Component {
|
|||
this.elem.addEventListener('click', this.onClick.bind(this));
|
||||
|
||||
let lastSearch = 0;
|
||||
this.searchInput.addEventListener('input', event => {
|
||||
this.searchInput.addEventListener('input', () => {
|
||||
lastSearch = Date.now();
|
||||
this.showLoading();
|
||||
setTimeout(() => {
|
||||
|
@ -43,26 +43,26 @@ export class EntitySelector extends Component {
|
|||
});
|
||||
|
||||
// Keyboard navigation
|
||||
onChildEvent(this.$el, '[data-entity-type]', 'keydown', (e, el) => {
|
||||
if (e.ctrlKey && e.code === 'Enter') {
|
||||
onChildEvent(this.$el, '[data-entity-type]', 'keydown', event => {
|
||||
if (event.ctrlKey && event.code === 'Enter') {
|
||||
const form = this.$el.closest('form');
|
||||
if (form) {
|
||||
form.submit();
|
||||
e.preventDefault();
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.code === 'ArrowDown') {
|
||||
if (event.code === 'ArrowDown') {
|
||||
this.focusAdjacent(true);
|
||||
}
|
||||
if (e.code === 'ArrowUp') {
|
||||
if (event.code === 'ArrowUp') {
|
||||
this.focusAdjacent(false);
|
||||
}
|
||||
});
|
||||
|
||||
this.searchInput.addEventListener('keydown', e => {
|
||||
if (e.code === 'ArrowDown') {
|
||||
this.searchInput.addEventListener('keydown', event => {
|
||||
if (event.code === 'ArrowDown') {
|
||||
this.focusAdjacent(true);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ import {Component} from './component';
|
|||
|
||||
export class ExpandToggle extends Component {
|
||||
|
||||
setup(elem) {
|
||||
setup() {
|
||||
this.targetSelector = this.$opts.targetSelector;
|
||||
this.isOpen = this.$opts.isOpen === 'true';
|
||||
this.updateEndpoint = this.$opts.updateEndpoint;
|
||||
|
@ -25,7 +25,8 @@ export class ExpandToggle extends Component {
|
|||
|
||||
const matchingElems = document.querySelectorAll(this.targetSelector);
|
||||
for (const match of matchingElems) {
|
||||
this.isOpen ? this.close(match) : this.open(match);
|
||||
const action = this.isOpen ? this.close : this.open;
|
||||
action(match);
|
||||
}
|
||||
|
||||
this.isOpen = !this.isOpen;
|
||||
|
|
|
@ -50,20 +50,20 @@ export class ImageManager extends Component {
|
|||
event.preventDefault();
|
||||
});
|
||||
|
||||
onSelect(this.cancelSearch, event => {
|
||||
onSelect(this.cancelSearch, () => {
|
||||
this.resetListView();
|
||||
this.resetSearchView();
|
||||
this.loadGallery();
|
||||
this.cancelSearch.classList.remove('active');
|
||||
});
|
||||
|
||||
this.searchInput.addEventListener('input', event => {
|
||||
this.searchInput.addEventListener('input', () => {
|
||||
this.cancelSearch.classList.toggle('active', this.searchInput.value.trim());
|
||||
});
|
||||
|
||||
onChildEvent(this.listContainer, '.load-more', 'click', async event => {
|
||||
showLoading(event.target);
|
||||
this.page++;
|
||||
this.page += 1;
|
||||
await this.loadGallery();
|
||||
event.target.remove();
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ export class ImageManager extends Component {
|
|||
this.listContainer.addEventListener('event-emit-select-image', this.onImageSelectEvent.bind(this));
|
||||
|
||||
this.listContainer.addEventListener('error', event => {
|
||||
event.target.src = baseUrl('loading_error.png');
|
||||
event.target.src = window.baseUrl('loading_error.png');
|
||||
}, true);
|
||||
|
||||
onSelect(this.selectButton, () => {
|
||||
|
@ -81,7 +81,7 @@ export class ImageManager extends Component {
|
|||
this.hide();
|
||||
});
|
||||
|
||||
onChildEvent(this.formContainer, '#image-manager-delete', 'click', event => {
|
||||
onChildEvent(this.formContainer, '#image-manager-delete', 'click', () => {
|
||||
if (this.lastSelected) {
|
||||
this.loadImageEditForm(this.lastSelected.id, true);
|
||||
}
|
||||
|
|
|
@ -1,59 +1,59 @@
|
|||
export {AddRemoveRows} from './add-remove-rows.js';
|
||||
export {AjaxDeleteRow} from './ajax-delete-row.js';
|
||||
export {AjaxForm} from './ajax-form.js';
|
||||
export {Attachments} from './attachments.js';
|
||||
export {AttachmentsList} from './attachments-list.js';
|
||||
export {AutoSuggest} from './auto-suggest.js';
|
||||
export {AutoSubmit} from './auto-submit.js';
|
||||
export {BackToTop} from './back-to-top.js';
|
||||
export {BookSort} from './book-sort.js';
|
||||
export {ChapterContents} from './chapter-contents.js';
|
||||
export {CodeEditor} from './code-editor.js';
|
||||
export {CodeHighlighter} from './code-highlighter.js';
|
||||
export {CodeTextarea} from './code-textarea.js';
|
||||
export {Collapsible} from './collapsible.js';
|
||||
export {AddRemoveRows} from './add-remove-rows';
|
||||
export {AjaxDeleteRow} from './ajax-delete-row';
|
||||
export {AjaxForm} from './ajax-form';
|
||||
export {Attachments} from './attachments';
|
||||
export {AttachmentsList} from './attachments-list';
|
||||
export {AutoSuggest} from './auto-suggest';
|
||||
export {AutoSubmit} from './auto-submit';
|
||||
export {BackToTop} from './back-to-top';
|
||||
export {BookSort} from './book-sort';
|
||||
export {ChapterContents} from './chapter-contents';
|
||||
export {CodeEditor} from './code-editor';
|
||||
export {CodeHighlighter} from './code-highlighter';
|
||||
export {CodeTextarea} from './code-textarea';
|
||||
export {Collapsible} from './collapsible';
|
||||
export {ConfirmDialog} from './confirm-dialog';
|
||||
export {CustomCheckbox} from './custom-checkbox.js';
|
||||
export {DetailsHighlighter} from './details-highlighter.js';
|
||||
export {Dropdown} from './dropdown.js';
|
||||
export {DropdownSearch} from './dropdown-search.js';
|
||||
export {Dropzone} from './dropzone.js';
|
||||
export {EditorToolbox} from './editor-toolbox.js';
|
||||
export {CustomCheckbox} from './custom-checkbox';
|
||||
export {DetailsHighlighter} from './details-highlighter';
|
||||
export {Dropdown} from './dropdown';
|
||||
export {DropdownSearch} from './dropdown-search';
|
||||
export {Dropzone} from './dropzone';
|
||||
export {EditorToolbox} from './editor-toolbox';
|
||||
export {EntityPermissions} from './entity-permissions';
|
||||
export {EntitySearch} from './entity-search.js';
|
||||
export {EntitySelector} from './entity-selector.js';
|
||||
export {EntitySelectorPopup} from './entity-selector-popup.js';
|
||||
export {EventEmitSelect} from './event-emit-select.js';
|
||||
export {ExpandToggle} from './expand-toggle.js';
|
||||
export {GlobalSearch} from './global-search.js';
|
||||
export {HeaderMobileToggle} from './header-mobile-toggle.js';
|
||||
export {ImageManager} from './image-manager.js';
|
||||
export {ImagePicker} from './image-picker.js';
|
||||
export {ListSortControl} from './list-sort-control.js';
|
||||
export {MarkdownEditor} from './markdown-editor.js';
|
||||
export {NewUserPassword} from './new-user-password.js';
|
||||
export {Notification} from './notification.js';
|
||||
export {OptionalInput} from './optional-input.js';
|
||||
export {PageComments} from './page-comments.js';
|
||||
export {PageDisplay} from './page-display.js';
|
||||
export {PageEditor} from './page-editor.js';
|
||||
export {PagePicker} from './page-picker.js';
|
||||
export {PermissionsTable} from './permissions-table.js';
|
||||
export {Pointer} from './pointer.js';
|
||||
export {Popup} from './popup.js';
|
||||
export {SettingAppColorScheme} from './setting-app-color-scheme.js';
|
||||
export {SettingColorPicker} from './setting-color-picker.js';
|
||||
export {SettingHomepageControl} from './setting-homepage-control.js';
|
||||
export {ShelfSort} from './shelf-sort.js';
|
||||
export {EntitySearch} from './entity-search';
|
||||
export {EntitySelector} from './entity-selector';
|
||||
export {EntitySelectorPopup} from './entity-selector-popup';
|
||||
export {EventEmitSelect} from './event-emit-select';
|
||||
export {ExpandToggle} from './expand-toggle';
|
||||
export {GlobalSearch} from './global-search';
|
||||
export {HeaderMobileToggle} from './header-mobile-toggle';
|
||||
export {ImageManager} from './image-manager';
|
||||
export {ImagePicker} from './image-picker';
|
||||
export {ListSortControl} from './list-sort-control';
|
||||
export {MarkdownEditor} from './markdown-editor';
|
||||
export {NewUserPassword} from './new-user-password';
|
||||
export {Notification} from './notification';
|
||||
export {OptionalInput} from './optional-input';
|
||||
export {PageComments} from './page-comments';
|
||||
export {PageDisplay} from './page-display';
|
||||
export {PageEditor} from './page-editor';
|
||||
export {PagePicker} from './page-picker';
|
||||
export {PermissionsTable} from './permissions-table';
|
||||
export {Pointer} from './pointer';
|
||||
export {Popup} from './popup';
|
||||
export {SettingAppColorScheme} from './setting-app-color-scheme';
|
||||
export {SettingColorPicker} from './setting-color-picker';
|
||||
export {SettingHomepageControl} from './setting-homepage-control';
|
||||
export {ShelfSort} from './shelf-sort';
|
||||
export {Shortcuts} from './shortcuts';
|
||||
export {ShortcutInput} from './shortcut-input';
|
||||
export {SortableList} from './sortable-list.js';
|
||||
export {SubmitOnChange} from './submit-on-change.js';
|
||||
export {Tabs} from './tabs.js';
|
||||
export {TagManager} from './tag-manager.js';
|
||||
export {TemplateManager} from './template-manager.js';
|
||||
export {ToggleSwitch} from './toggle-switch.js';
|
||||
export {TriLayout} from './tri-layout.js';
|
||||
export {UserSelect} from './user-select.js';
|
||||
export {SortableList} from './sortable-list';
|
||||
export {SubmitOnChange} from './submit-on-change';
|
||||
export {Tabs} from './tabs';
|
||||
export {TagManager} from './tag-manager';
|
||||
export {TemplateManager} from './template-manager';
|
||||
export {ToggleSwitch} from './toggle-switch';
|
||||
export {TriLayout} from './tri-layout';
|
||||
export {UserSelect} from './user-select';
|
||||
export {WebhookEvents} from './webhook-events';
|
||||
export {WysiwygEditor} from './wysiwyg-editor.js';
|
||||
export {WysiwygEditor} from './wysiwyg-editor';
|
||||
|
|
|
@ -82,7 +82,7 @@ export class MarkdownEditor extends Component {
|
|||
}
|
||||
|
||||
handleDividerDrag() {
|
||||
this.divider.addEventListener('pointerdown', event => {
|
||||
this.divider.addEventListener('pointerdown', () => {
|
||||
const wrapRect = this.elem.getBoundingClientRect();
|
||||
const moveListener = event => {
|
||||
const xRel = event.pageX - wrapRect.left;
|
||||
|
@ -90,7 +90,7 @@ export class MarkdownEditor extends Component {
|
|||
this.displayWrap.style.flexBasis = `${100 - xPct}%`;
|
||||
this.editor.settings.set('editorWidth', xPct);
|
||||
};
|
||||
const upListener = event => {
|
||||
const upListener = () => {
|
||||
window.removeEventListener('pointermove', moveListener);
|
||||
window.removeEventListener('pointerup', upListener);
|
||||
this.display.style.pointerEvents = null;
|
||||
|
|
|
@ -100,7 +100,7 @@ export class PageComments extends Component {
|
|||
deleteComment(commentElem) {
|
||||
const id = commentElem.getAttribute('comment');
|
||||
this.showLoading(commentElem.querySelector('[comment-content]'));
|
||||
window.$http.delete(`/comment/${id}`).then(resp => {
|
||||
window.$http.delete(`/comment/${id}`).then(() => {
|
||||
commentElem.parentNode.removeChild(commentElem);
|
||||
window.$events.success(this.deletedText);
|
||||
this.updateCount();
|
||||
|
|
|
@ -2,6 +2,33 @@ import * as DOM from '../services/dom';
|
|||
import {scrollAndHighlightElement} from '../services/util';
|
||||
import {Component} from './component';
|
||||
|
||||
function toggleAnchorHighlighting(elementId, shouldHighlight) {
|
||||
DOM.forEach(`a[href="#${elementId}"]`, anchor => {
|
||||
anchor.closest('li').classList.toggle('current-heading', shouldHighlight);
|
||||
});
|
||||
}
|
||||
|
||||
function headingVisibilityChange(entries) {
|
||||
for (const entry of entries) {
|
||||
const isVisible = (entry.intersectionRatio === 1);
|
||||
toggleAnchorHighlighting(entry.target.id, isVisible);
|
||||
}
|
||||
}
|
||||
|
||||
function addNavObserver(headings) {
|
||||
// Setup the intersection observer.
|
||||
const intersectOpts = {
|
||||
rootMargin: '0px 0px 0px 0px',
|
||||
threshold: 1.0,
|
||||
};
|
||||
const pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts);
|
||||
|
||||
// observe each heading
|
||||
for (const heading of headings) {
|
||||
pageNavObserver.observe(heading);
|
||||
}
|
||||
}
|
||||
|
||||
export class PageDisplay extends Component {
|
||||
|
||||
setup() {
|
||||
|
@ -58,33 +85,6 @@ export class PageDisplay extends Component {
|
|||
if (headings.length > 0 && pageNav !== null) {
|
||||
addNavObserver(headings);
|
||||
}
|
||||
|
||||
function addNavObserver(headings) {
|
||||
// Setup the intersection observer.
|
||||
const intersectOpts = {
|
||||
rootMargin: '0px 0px 0px 0px',
|
||||
threshold: 1.0,
|
||||
};
|
||||
const pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts);
|
||||
|
||||
// observe each heading
|
||||
for (const heading of headings) {
|
||||
pageNavObserver.observe(heading);
|
||||
}
|
||||
}
|
||||
|
||||
function headingVisibilityChange(entries, observer) {
|
||||
for (const entry of entries) {
|
||||
const isVisible = (entry.intersectionRatio === 1);
|
||||
toggleAnchorHighlighting(entry.target.id, isVisible);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAnchorHighlighting(elementId, shouldHighlight) {
|
||||
DOM.forEach(`a[href="#${elementId}"]`, anchor => {
|
||||
anchor.closest('li').classList.toggle('current-heading', shouldHighlight);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setupDetailsCodeBlockRefresh() {
|
||||
|
|
|
@ -59,7 +59,9 @@ export class PageEditor extends Component {
|
|||
window.$events.listen('editor-save-page', this.savePage.bind(this));
|
||||
|
||||
// Listen to content changes from the editor
|
||||
const onContentChange = () => this.autoSave.pendingChange = true;
|
||||
const onContentChange = () => {
|
||||
this.autoSave.pendingChange = true;
|
||||
};
|
||||
window.$events.listen('editor-html-change', onContentChange);
|
||||
window.$events.listen('editor-markdown-change', onContentChange);
|
||||
|
||||
|
@ -80,7 +82,8 @@ export class PageEditor extends Component {
|
|||
|
||||
setInitialFocus() {
|
||||
if (this.hasDefaultTitle) {
|
||||
return this.titleElem.select();
|
||||
this.titleElem.select();
|
||||
return;
|
||||
}
|
||||
|
||||
window.setTimeout(() => {
|
||||
|
@ -133,7 +136,9 @@ export class PageEditor extends Component {
|
|||
try {
|
||||
const saveKey = `draft-save-fail-${(new Date()).toISOString()}`;
|
||||
window.localStorage.setItem(saveKey, JSON.stringify(data));
|
||||
} catch (err) {}
|
||||
} catch (lsErr) {
|
||||
console.error(lsErr);
|
||||
}
|
||||
|
||||
window.$events.emit('error', this.autosaveFailText);
|
||||
}
|
||||
|
@ -154,7 +159,8 @@ export class PageEditor extends Component {
|
|||
try {
|
||||
response = await window.$http.get(`/ajax/page/${this.pageId}`);
|
||||
} catch (e) {
|
||||
return console.error(e);
|
||||
console.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.autoSave.interval) {
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import {Component} from './component';
|
||||
|
||||
function toggleElem(elem, show) {
|
||||
elem.style.display = show ? null : 'none';
|
||||
}
|
||||
|
||||
export class PagePicker extends Component {
|
||||
|
||||
setup() {
|
||||
|
@ -18,7 +22,7 @@ export class PagePicker extends Component {
|
|||
this.selectButton.addEventListener('click', this.showPopup.bind(this));
|
||||
this.display.parentElement.addEventListener('click', this.showPopup.bind(this));
|
||||
|
||||
this.resetButton.addEventListener('click', event => {
|
||||
this.resetButton.addEventListener('click', () => {
|
||||
this.setValue('', '');
|
||||
});
|
||||
}
|
||||
|
@ -55,7 +59,3 @@ export class PagePicker extends Component {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
function toggleElem(elem, show) {
|
||||
elem.style.display = show ? null : 'none';
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export class Pointer extends Component {
|
|||
|
||||
setupListeners() {
|
||||
// Copy on copy button click
|
||||
this.button.addEventListener('click', event => {
|
||||
this.button.addEventListener('click', () => {
|
||||
copyTextToClipboard(this.input.value);
|
||||
});
|
||||
|
||||
|
@ -46,7 +46,7 @@ export class Pointer extends Component {
|
|||
});
|
||||
|
||||
// Hide pointer when clicking away
|
||||
DOM.onEvents(document.body, ['click', 'focus'], event => {
|
||||
DOM.onEvents(document.body, ['click', 'focus'], () => {
|
||||
if (!this.showing || this.isSelection) return;
|
||||
this.hidePointer();
|
||||
});
|
||||
|
|
|
@ -26,11 +26,11 @@ export class Popup extends Component {
|
|||
|
||||
this.container.addEventListener('click', event => {
|
||||
if (event.target === this.container && lastMouseDownTarget === this.container) {
|
||||
return this.hide();
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
|
||||
onSelect(this.hideButtons, e => this.hide());
|
||||
onSelect(this.hideButtons, () => this.hide());
|
||||
}
|
||||
|
||||
hide(onComplete = null) {
|
||||
|
|
|
@ -59,7 +59,6 @@ export class SettingAppColorScheme extends Component {
|
|||
const rgb = this.hexToRgb(hexVal);
|
||||
const rgbLightVal = `rgba(${[rgb.r, rgb.g, rgb.b, '0.15'].join(',')})`;
|
||||
|
||||
console.log(input.name, lightName, hexVal, rgbLightVal);
|
||||
const lightColorInput = this.container.querySelector(`input[name="${lightName}"][type="hidden"]`);
|
||||
lightColorInput.value = rgbLightVal;
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ import {Component} from './component';
|
|||
* @type {Object<string, function(HTMLElement, HTMLElement, HTMLElement)>}
|
||||
*/
|
||||
const itemActions = {
|
||||
move_up(item, shelfBooksList, allBooksList) {
|
||||
move_up(item) {
|
||||
const list = item.parentNode;
|
||||
const index = Array.from(list.children).indexOf(item);
|
||||
const newIndex = Math.max(index - 1, 0);
|
||||
list.insertBefore(item, list.children[newIndex] || null);
|
||||
},
|
||||
move_down(item, shelfBooksList, allBooksList) {
|
||||
move_down(item) {
|
||||
const list = item.parentNode;
|
||||
const index = Array.from(list.children).indexOf(item);
|
||||
const newIndex = Math.min(index + 2, list.children.length);
|
||||
|
@ -20,7 +20,7 @@ const itemActions = {
|
|||
remove(item, shelfBooksList, allBooksList) {
|
||||
allBooksList.appendChild(item);
|
||||
},
|
||||
add(item, shelfBooksList, allBooksList) {
|
||||
add(item, shelfBooksList) {
|
||||
shelfBooksList.appendChild(item);
|
||||
},
|
||||
};
|
||||
|
@ -62,7 +62,7 @@ export class ShelfSort extends Component {
|
|||
}
|
||||
});
|
||||
|
||||
this.bookSearchInput.addEventListener('input', event => {
|
||||
this.bookSearchInput.addEventListener('input', () => {
|
||||
this.filterBooksByName(this.bookSearchInput.value);
|
||||
});
|
||||
|
||||
|
@ -121,10 +121,10 @@ export class ShelfSort extends Component {
|
|||
const bProp = bookB.dataset[sortProperty].toLowerCase();
|
||||
|
||||
if (reverse) {
|
||||
return aProp < bProp ? (aProp === bProp ? 0 : 1) : -1;
|
||||
return bProp.localeCompare(aProp);
|
||||
}
|
||||
|
||||
return aProp < bProp ? (aProp === bProp ? 0 : -1) : 1;
|
||||
return aProp.localeCompare(bProp);
|
||||
});
|
||||
|
||||
for (const book of books) {
|
||||
|
|
|
@ -33,7 +33,8 @@ export class Shortcuts extends Component {
|
|||
|
||||
window.addEventListener('keydown', event => {
|
||||
if (event.key === '?') {
|
||||
this.hintsShowing ? this.hideHints() : this.showHints();
|
||||
const action = this.hintsShowing ? this.hideHints : this.showHints;
|
||||
action();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@ export class TemplateManager extends Component {
|
|||
});
|
||||
|
||||
// Search submit button press
|
||||
this.searchButton.addEventListener('click', event => this.performSearch());
|
||||
this.searchButton.addEventListener('click', () => this.performSearch());
|
||||
|
||||
// Search cancel button press
|
||||
this.searchCancel.addEventListener('click', event => {
|
||||
this.searchCancel.addEventListener('click', () => {
|
||||
this.searchInput.value = '';
|
||||
this.performSearch();
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@ export class TriLayout extends Component {
|
|||
|
||||
// Watch layout changes
|
||||
this.updateLayout();
|
||||
window.addEventListener('resize', event => {
|
||||
window.addEventListener('resize', () => {
|
||||
this.updateLayout();
|
||||
}, {passive: true});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import DrawIO from '../services/drawio';
|
||||
import * as DrawIO from '../services/drawio';
|
||||
|
||||
export class Actions {
|
||||
|
||||
|
@ -140,7 +140,7 @@ export class Actions {
|
|||
} else {
|
||||
window.$events.emit('error', this.editor.config.text.imageUploadError);
|
||||
}
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
// Make the editor full screen
|
||||
|
@ -165,7 +165,7 @@ export class Actions {
|
|||
scrollToLine = lineCount;
|
||||
break;
|
||||
}
|
||||
lineCount++;
|
||||
lineCount += 1;
|
||||
}
|
||||
|
||||
if (scrollToLine === -1) {
|
||||
|
@ -258,22 +258,31 @@ export class Actions {
|
|||
* @param {String} end
|
||||
*/
|
||||
wrapSelection(start, end) {
|
||||
const selectionRange = this.#getSelectionRange();
|
||||
const selectionText = this.#getSelectionText(selectionRange);
|
||||
if (!selectionText) return this.#wrapLine(start, end);
|
||||
const selectRange = this.#getSelectionRange();
|
||||
const selectionText = this.#getSelectionText(selectRange);
|
||||
if (!selectionText) {
|
||||
this.#wrapLine(start, end);
|
||||
return;
|
||||
}
|
||||
|
||||
let newSelectionText = selectionText;
|
||||
let newRange;
|
||||
|
||||
if (selectionText.startsWith(start) && selectionText.endsWith(end)) {
|
||||
newSelectionText = selectionText.slice(start.length, selectionText.length - end.length);
|
||||
newRange = selectionRange.extend(selectionRange.from, selectionRange.to - (start.length + end.length));
|
||||
newRange = selectRange.extend(selectRange.from, selectRange.to - (start.length + end.length));
|
||||
} else {
|
||||
newSelectionText = `${start}${selectionText}${end}`;
|
||||
newRange = selectionRange.extend(selectionRange.from, selectionRange.to + (start.length + end.length));
|
||||
newRange = selectRange.extend(selectRange.from, selectRange.to + (start.length + end.length));
|
||||
}
|
||||
|
||||
this.#dispatchChange(selectionRange.from, selectionRange.to, newSelectionText, newRange.anchor, newRange.head);
|
||||
this.#dispatchChange(
|
||||
selectRange.from,
|
||||
selectRange.to,
|
||||
newSelectionText,
|
||||
newRange.anchor,
|
||||
newRange.head,
|
||||
);
|
||||
}
|
||||
|
||||
replaceLineStartForOrderedList() {
|
||||
|
@ -314,7 +323,13 @@ export class Actions {
|
|||
const newFormat = formats[newFormatIndex];
|
||||
const newContent = line.text.replace(matches[0], matches[0].replace(format, newFormat));
|
||||
const lineDiff = newContent.length - line.text.length;
|
||||
this.#dispatchChange(line.from, line.to, newContent, selectionRange.anchor + lineDiff, selectionRange.head + lineDiff);
|
||||
this.#dispatchChange(
|
||||
line.from,
|
||||
line.to,
|
||||
newContent,
|
||||
selectionRange.anchor + lineDiff,
|
||||
selectionRange.head + lineDiff,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,7 +414,7 @@ export class Actions {
|
|||
} catch (err) {
|
||||
window.$events.emit('error', this.editor.config.text.imageUploadError);
|
||||
this.#findAndReplaceContent(placeHolderText, '');
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,7 +447,8 @@ export class Actions {
|
|||
*/
|
||||
#replaceSelection(newContent, cursorOffset = 0, selectionRange = null) {
|
||||
selectionRange = selectionRange || this.editor.cm.state.selection.main;
|
||||
this.#dispatchChange(selectionRange.from, selectionRange.to, newContent, selectionRange.from + cursorOffset);
|
||||
const selectFrom = selectionRange.from + cursorOffset;
|
||||
this.#dispatchChange(selectionRange.from, selectionRange.to, newContent, selectFrom);
|
||||
this.focus();
|
||||
}
|
||||
|
||||
|
@ -510,6 +526,9 @@ export class Actions {
|
|||
|
||||
if (selectFrom) {
|
||||
tr.selection = {anchor: selectFrom};
|
||||
if (selectTo) {
|
||||
tr.selection.head = selectTo;
|
||||
}
|
||||
}
|
||||
|
||||
this.editor.cm.dispatch(tr);
|
||||
|
|
|
@ -21,7 +21,9 @@ export async function init(editor) {
|
|||
|
||||
const onScrollDebounced = debounce(editor.actions.syncDisplayPosition.bind(editor.actions), 100, false);
|
||||
let syncActive = editor.settings.get('scrollSync');
|
||||
editor.settings.onChange('scrollSync', val => syncActive = val);
|
||||
editor.settings.onChange('scrollSync', val => {
|
||||
syncActive = val;
|
||||
});
|
||||
|
||||
const domEventHandlers = {
|
||||
// Handle scroll to sync display view
|
||||
|
|
|
@ -21,7 +21,7 @@ export class Settings {
|
|||
|
||||
listenToInputChanges(inputs) {
|
||||
for (const input of inputs) {
|
||||
input.addEventListener('change', event => {
|
||||
input.addEventListener('change', () => {
|
||||
const name = input.getAttribute('name').replace('md-', '');
|
||||
this.set(name, input.checked);
|
||||
});
|
||||
|
|
|
@ -7,35 +7,35 @@ function provide(editor) {
|
|||
const shortcuts = {};
|
||||
|
||||
// Insert Image shortcut
|
||||
shortcuts['Shift-Mod-i'] = cm => editor.actions.insertImage();
|
||||
shortcuts['Shift-Mod-i'] = () => editor.actions.insertImage();
|
||||
|
||||
// Save draft
|
||||
shortcuts['Mod-s'] = cm => window.$events.emit('editor-save-draft');
|
||||
shortcuts['Mod-s'] = () => window.$events.emit('editor-save-draft');
|
||||
|
||||
// Save page
|
||||
shortcuts['Mod-Enter'] = cm => window.$events.emit('editor-save-page');
|
||||
shortcuts['Mod-Enter'] = () => window.$events.emit('editor-save-page');
|
||||
|
||||
// Show link selector
|
||||
shortcuts['Shift-Mod-k'] = cm => editor.actions.showLinkSelector();
|
||||
shortcuts['Shift-Mod-k'] = () => editor.actions.showLinkSelector();
|
||||
|
||||
// Insert Link
|
||||
shortcuts['Mod-k'] = cm => editor.actions.insertLink();
|
||||
shortcuts['Mod-k'] = () => editor.actions.insertLink();
|
||||
|
||||
// FormatShortcuts
|
||||
shortcuts['Mod-1'] = cm => editor.actions.replaceLineStart('##');
|
||||
shortcuts['Mod-2'] = cm => editor.actions.replaceLineStart('###');
|
||||
shortcuts['Mod-3'] = cm => editor.actions.replaceLineStart('####');
|
||||
shortcuts['Mod-4'] = cm => editor.actions.replaceLineStart('#####');
|
||||
shortcuts['Mod-5'] = cm => editor.actions.replaceLineStart('');
|
||||
shortcuts['Mod-d'] = cm => editor.actions.replaceLineStart('');
|
||||
shortcuts['Mod-6'] = cm => editor.actions.replaceLineStart('>');
|
||||
shortcuts['Mod-q'] = cm => editor.actions.replaceLineStart('>');
|
||||
shortcuts['Mod-7'] = cm => editor.actions.wrapSelection('\n```\n', '\n```');
|
||||
shortcuts['Mod-8'] = cm => editor.actions.wrapSelection('`', '`');
|
||||
shortcuts['Shift-Mod-e'] = cm => editor.actions.wrapSelection('`', '`');
|
||||
shortcuts['Mod-9'] = cm => editor.actions.cycleCalloutTypeAtSelection();
|
||||
shortcuts['Mod-p'] = cm => editor.actions.replaceLineStart('-');
|
||||
shortcuts['Mod-o'] = cm => editor.actions.replaceLineStartForOrderedList();
|
||||
shortcuts['Mod-1'] = () => editor.actions.replaceLineStart('##');
|
||||
shortcuts['Mod-2'] = () => editor.actions.replaceLineStart('###');
|
||||
shortcuts['Mod-3'] = () => editor.actions.replaceLineStart('####');
|
||||
shortcuts['Mod-4'] = () => editor.actions.replaceLineStart('#####');
|
||||
shortcuts['Mod-5'] = () => editor.actions.replaceLineStart('');
|
||||
shortcuts['Mod-d'] = () => editor.actions.replaceLineStart('');
|
||||
shortcuts['Mod-6'] = () => editor.actions.replaceLineStart('>');
|
||||
shortcuts['Mod-q'] = () => editor.actions.replaceLineStart('>');
|
||||
shortcuts['Mod-7'] = () => editor.actions.wrapSelection('\n```\n', '\n```');
|
||||
shortcuts['Mod-8'] = () => editor.actions.wrapSelection('`', '`');
|
||||
shortcuts['Shift-Mod-e'] = () => editor.actions.wrapSelection('`', '`');
|
||||
shortcuts['Mod-9'] = () => editor.actions.cycleCalloutTypeAtSelection();
|
||||
shortcuts['Mod-p'] = () => editor.actions.replaceLineStart('-');
|
||||
shortcuts['Mod-o'] = () => editor.actions.replaceLineStartForOrderedList();
|
||||
|
||||
return shortcuts;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,53 @@
|
|||
*/
|
||||
const animateStylesCleanupMap = new WeakMap();
|
||||
|
||||
/**
|
||||
* Animate the css styles of an element using FLIP animation techniques.
|
||||
* Styles must be an object where the keys are style properties, camelcase, and the values
|
||||
* are an array of two items in the format [initialValue, finalValue]
|
||||
* @param {Element} element
|
||||
* @param {Object} styles
|
||||
* @param {Number} animTime
|
||||
* @param {Function} onComplete
|
||||
*/
|
||||
function animateStyles(element, styles, animTime = 400, onComplete = null) {
|
||||
const styleNames = Object.keys(styles);
|
||||
for (const style of styleNames) {
|
||||
element.style[style] = styles[style][0];
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
for (const style of styleNames) {
|
||||
element.style[style] = null;
|
||||
}
|
||||
element.style.transition = null;
|
||||
element.removeEventListener('transitionend', cleanup);
|
||||
animateStylesCleanupMap.delete(element);
|
||||
if (onComplete) onComplete();
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
element.style.transition = `all ease-in-out ${animTime}ms`;
|
||||
for (const style of styleNames) {
|
||||
element.style[style] = styles[style][1];
|
||||
}
|
||||
|
||||
element.addEventListener('transitionend', cleanup);
|
||||
animateStylesCleanupMap.set(element, cleanup);
|
||||
}, 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the active cleanup action for the given element.
|
||||
* @param {Element} element
|
||||
*/
|
||||
function cleanupExistingElementAnimation(element) {
|
||||
if (animateStylesCleanupMap.has(element)) {
|
||||
const oldCleanup = animateStylesCleanupMap.get(element);
|
||||
oldCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fade in the given element.
|
||||
* @param {Element} element
|
||||
|
@ -113,50 +160,3 @@ export function transitionHeight(element, animTime = 400) {
|
|||
animateStyles(element, animStyles, animTime);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate the css styles of an element using FLIP animation techniques.
|
||||
* Styles must be an object where the keys are style properties, camelcase, and the values
|
||||
* are an array of two items in the format [initialValue, finalValue]
|
||||
* @param {Element} element
|
||||
* @param {Object} styles
|
||||
* @param {Number} animTime
|
||||
* @param {Function} onComplete
|
||||
*/
|
||||
function animateStyles(element, styles, animTime = 400, onComplete = null) {
|
||||
const styleNames = Object.keys(styles);
|
||||
for (const style of styleNames) {
|
||||
element.style[style] = styles[style][0];
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
for (const style of styleNames) {
|
||||
element.style[style] = null;
|
||||
}
|
||||
element.style.transition = null;
|
||||
element.removeEventListener('transitionend', cleanup);
|
||||
animateStylesCleanupMap.delete(element);
|
||||
if (onComplete) onComplete();
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
element.style.transition = `all ease-in-out ${animTime}ms`;
|
||||
for (const style of styleNames) {
|
||||
element.style[style] = styles[style][1];
|
||||
}
|
||||
|
||||
element.addEventListener('transitionend', cleanup);
|
||||
animateStylesCleanupMap.set(element, cleanup);
|
||||
}, 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the active cleanup action for the given element.
|
||||
* @param {Element} element
|
||||
*/
|
||||
function cleanupExistingElementAnimation(element) {
|
||||
if (animateStylesCleanupMap.has(element)) {
|
||||
const oldCleanup = animateStylesCleanupMap.get(element);
|
||||
oldCleanup();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,44 +19,6 @@ const componentModelMap = {};
|
|||
*/
|
||||
const elementComponentMap = new WeakMap();
|
||||
|
||||
/**
|
||||
* Initialize a component instance on the given dom element.
|
||||
* @param {String} name
|
||||
* @param {Element} element
|
||||
*/
|
||||
function initComponent(name, element) {
|
||||
/** @type {Function<Component>|undefined} * */
|
||||
const componentModel = componentModelMap[name];
|
||||
if (componentModel === undefined) return;
|
||||
|
||||
// Create our component instance
|
||||
/** @type {Component} * */
|
||||
let instance;
|
||||
try {
|
||||
instance = new componentModel();
|
||||
instance.$name = name;
|
||||
instance.$el = element;
|
||||
const allRefs = parseRefs(name, element);
|
||||
instance.$refs = allRefs.refs;
|
||||
instance.$manyRefs = allRefs.manyRefs;
|
||||
instance.$opts = parseOpts(name, element);
|
||||
instance.setup();
|
||||
} catch (e) {
|
||||
console.error('Failed to create component', e, name, element);
|
||||
}
|
||||
|
||||
// Add to global listing
|
||||
if (typeof components[name] === 'undefined') {
|
||||
components[name] = [];
|
||||
}
|
||||
components[name].push(instance);
|
||||
|
||||
// Add to element mapping
|
||||
const elComponents = elementComponentMap.get(element) || {};
|
||||
elComponents[name] = instance;
|
||||
elementComponentMap.set(element, elComponents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse out the element references within the given element
|
||||
* for the given component name.
|
||||
|
@ -93,13 +55,13 @@ function parseRefs(name, element) {
|
|||
|
||||
/**
|
||||
* Parse out the element component options.
|
||||
* @param {String} name
|
||||
* @param {String} componentName
|
||||
* @param {Element} element
|
||||
* @return {Object<String, String>}
|
||||
*/
|
||||
function parseOpts(name, element) {
|
||||
function parseOpts(componentName, element) {
|
||||
const opts = {};
|
||||
const prefix = `option:${name}:`;
|
||||
const prefix = `option:${componentName}:`;
|
||||
for (const {name, value} of element.attributes) {
|
||||
if (name.startsWith(prefix)) {
|
||||
const optName = name.replace(prefix, '');
|
||||
|
@ -109,6 +71,44 @@ function parseOpts(name, element) {
|
|||
return opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a component instance on the given dom element.
|
||||
* @param {String} name
|
||||
* @param {Element} element
|
||||
*/
|
||||
function initComponent(name, element) {
|
||||
/** @type {Function<Component>|undefined} * */
|
||||
const ComponentModel = componentModelMap[name];
|
||||
if (ComponentModel === undefined) return;
|
||||
|
||||
// Create our component instance
|
||||
/** @type {Component} * */
|
||||
let instance;
|
||||
try {
|
||||
instance = new ComponentModel();
|
||||
instance.$name = name;
|
||||
instance.$el = element;
|
||||
const allRefs = parseRefs(name, element);
|
||||
instance.$refs = allRefs.refs;
|
||||
instance.$manyRefs = allRefs.manyRefs;
|
||||
instance.$opts = parseOpts(name, element);
|
||||
instance.setup();
|
||||
} catch (e) {
|
||||
console.error('Failed to create component', e, name, element);
|
||||
}
|
||||
|
||||
// Add to global listing
|
||||
if (typeof components[name] === 'undefined') {
|
||||
components[name] = [];
|
||||
}
|
||||
components[name].push(instance);
|
||||
|
||||
// Add to element mapping
|
||||
const elComponents = elementComponentMap.get(element) || {};
|
||||
elComponents[name] = instance;
|
||||
elementComponentMap.set(element, elComponents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all components found within the given element.
|
||||
* @param {Element|Document} parentElement
|
||||
|
|
|
@ -3,50 +3,8 @@ let lastApprovedOrigin;
|
|||
let onInit; let
|
||||
onSave;
|
||||
|
||||
/**
|
||||
* Show the draw.io editor.
|
||||
* @param {String} drawioUrl
|
||||
* @param {Function} onInitCallback - Must return a promise with the xml to load for the editor.
|
||||
* @param {Function} onSaveCallback - Is called with the drawing data on save.
|
||||
*/
|
||||
function show(drawioUrl, onInitCallback, onSaveCallback) {
|
||||
onInit = onInitCallback;
|
||||
onSave = onSaveCallback;
|
||||
|
||||
iFrame = document.createElement('iframe');
|
||||
iFrame.setAttribute('frameborder', '0');
|
||||
window.addEventListener('message', drawReceive);
|
||||
iFrame.setAttribute('src', drawioUrl);
|
||||
iFrame.setAttribute('class', 'fullscreen');
|
||||
iFrame.style.backgroundColor = '#FFFFFF';
|
||||
document.body.appendChild(iFrame);
|
||||
lastApprovedOrigin = (new URL(drawioUrl)).origin;
|
||||
}
|
||||
|
||||
function close() {
|
||||
drawEventClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive and handle a message event from the draw.io window.
|
||||
* @param {MessageEvent} event
|
||||
*/
|
||||
function drawReceive(event) {
|
||||
if (!event.data || event.data.length < 1) return;
|
||||
if (event.origin !== lastApprovedOrigin) return;
|
||||
|
||||
const message = JSON.parse(event.data);
|
||||
if (message.event === 'init') {
|
||||
drawEventInit();
|
||||
} else if (message.event === 'exit') {
|
||||
drawEventClose();
|
||||
} else if (message.event === 'save') {
|
||||
drawEventSave(message);
|
||||
} else if (message.event === 'export') {
|
||||
drawEventExport(message);
|
||||
} else if (message.event === 'configure') {
|
||||
drawEventConfigure();
|
||||
}
|
||||
function drawPostMessage(data) {
|
||||
iFrame.contentWindow.postMessage(JSON.stringify(data), lastApprovedOrigin);
|
||||
}
|
||||
|
||||
function drawEventExport(message) {
|
||||
|
@ -75,15 +33,54 @@ function drawEventConfigure() {
|
|||
}
|
||||
|
||||
function drawEventClose() {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
window.removeEventListener('message', drawReceive);
|
||||
if (iFrame) document.body.removeChild(iFrame);
|
||||
}
|
||||
|
||||
function drawPostMessage(data) {
|
||||
iFrame.contentWindow.postMessage(JSON.stringify(data), lastApprovedOrigin);
|
||||
/**
|
||||
* Receive and handle a message event from the draw.io window.
|
||||
* @param {MessageEvent} event
|
||||
*/
|
||||
function drawReceive(event) {
|
||||
if (!event.data || event.data.length < 1) return;
|
||||
if (event.origin !== lastApprovedOrigin) return;
|
||||
|
||||
const message = JSON.parse(event.data);
|
||||
if (message.event === 'init') {
|
||||
drawEventInit();
|
||||
} else if (message.event === 'exit') {
|
||||
drawEventClose();
|
||||
} else if (message.event === 'save') {
|
||||
drawEventSave(message);
|
||||
} else if (message.event === 'export') {
|
||||
drawEventExport(message);
|
||||
} else if (message.event === 'configure') {
|
||||
drawEventConfigure();
|
||||
}
|
||||
}
|
||||
|
||||
async function upload(imageData, pageUploadedToId) {
|
||||
/**
|
||||
* Show the draw.io editor.
|
||||
* @param {String} drawioUrl
|
||||
* @param {Function} onInitCallback - Must return a promise with the xml to load for the editor.
|
||||
* @param {Function} onSaveCallback - Is called with the drawing data on save.
|
||||
*/
|
||||
export function show(drawioUrl, onInitCallback, onSaveCallback) {
|
||||
onInit = onInitCallback;
|
||||
onSave = onSaveCallback;
|
||||
|
||||
iFrame = document.createElement('iframe');
|
||||
iFrame.setAttribute('frameborder', '0');
|
||||
window.addEventListener('message', drawReceive);
|
||||
iFrame.setAttribute('src', drawioUrl);
|
||||
iFrame.setAttribute('class', 'fullscreen');
|
||||
iFrame.style.backgroundColor = '#FFFFFF';
|
||||
document.body.appendChild(iFrame);
|
||||
lastApprovedOrigin = (new URL(drawioUrl)).origin;
|
||||
}
|
||||
|
||||
export async function upload(imageData, pageUploadedToId) {
|
||||
const data = {
|
||||
image: imageData,
|
||||
uploaded_to: pageUploadedToId,
|
||||
|
@ -92,12 +89,16 @@ async function upload(imageData, pageUploadedToId) {
|
|||
return resp.data;
|
||||
}
|
||||
|
||||
export function close() {
|
||||
drawEventClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an existing image, by fetching it as Base64 from the system.
|
||||
* @param drawingId
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function load(drawingId) {
|
||||
export async function load(drawingId) {
|
||||
try {
|
||||
const resp = await window.$http.get(window.baseUrl(`/images/drawio/base64/${drawingId}`));
|
||||
return `data:image/png;base64,${resp.data.content}`;
|
||||
|
@ -109,7 +110,3 @@ async function load(drawingId) {
|
|||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
show, close, upload, load,
|
||||
};
|
||||
|
|
|
@ -6,13 +6,12 @@ const stack = [];
|
|||
* @param {String} eventName
|
||||
* @param {*} eventData
|
||||
*/
|
||||
function emit(eventName, eventData) {
|
||||
export function emit(eventName, eventData) {
|
||||
stack.push({name: eventName, data: eventData});
|
||||
if (typeof listeners[eventName] === 'undefined') return this;
|
||||
const eventsToStart = listeners[eventName];
|
||||
for (let i = 0; i < eventsToStart.length; i++) {
|
||||
const event = eventsToStart[i];
|
||||
event(eventData);
|
||||
|
||||
const listenersToRun = listeners[eventName] || [];
|
||||
for (const listener of listenersToRun) {
|
||||
listener(eventData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +21,7 @@ function emit(eventName, eventData) {
|
|||
* @param {Function} callback
|
||||
* @returns {Events}
|
||||
*/
|
||||
function listen(eventName, callback) {
|
||||
export function listen(eventName, callback) {
|
||||
if (typeof listeners[eventName] === 'undefined') listeners[eventName] = [];
|
||||
listeners[eventName].push(callback);
|
||||
}
|
||||
|
@ -34,7 +33,7 @@ function listen(eventName, callback) {
|
|||
* @param {String} eventName
|
||||
* @param {Object} eventData
|
||||
*/
|
||||
function emitPublic(targetElement, eventName, eventData) {
|
||||
export function emitPublic(targetElement, eventName, eventData) {
|
||||
const event = new CustomEvent(eventName, {
|
||||
detail: eventData,
|
||||
bubbles: true,
|
||||
|
@ -43,34 +42,40 @@ function emitPublic(targetElement, eventName, eventData) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Notify of standard server-provided validation errors.
|
||||
* @param {Object} error
|
||||
* Emit a success event with the provided message.
|
||||
* @param {String} message
|
||||
*/
|
||||
function showValidationErrors(error) {
|
||||
if (!error.status) return;
|
||||
if (error.status === 422 && error.data) {
|
||||
const message = Object.values(error.data).flat().join('\n');
|
||||
emit('error', message);
|
||||
export function success(message) {
|
||||
emit('success', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit an error event with the provided message.
|
||||
* @param {String} message
|
||||
*/
|
||||
export function error(message) {
|
||||
emit('error', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify of standard server-provided validation errors.
|
||||
* @param {Object} responseErr
|
||||
*/
|
||||
export function showValidationErrors(responseErr) {
|
||||
if (!responseErr.status) return;
|
||||
if (responseErr.status === 422 && responseErr.data) {
|
||||
const message = Object.values(responseErr.data).flat().join('\n');
|
||||
error(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify standard server-provided error messages.
|
||||
* @param {Object} error
|
||||
* @param {Object} responseErr
|
||||
*/
|
||||
function showResponseError(error) {
|
||||
if (!error.status) return;
|
||||
if (error.status >= 400 && error.data && error.data.message) {
|
||||
emit('error', error.data.message);
|
||||
export function showResponseError(responseErr) {
|
||||
if (!responseErr.status) return;
|
||||
if (responseErr.status >= 400 && responseErr.data && responseErr.data.message) {
|
||||
error(responseErr.data.message);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
emit,
|
||||
emitPublic,
|
||||
listen,
|
||||
success: msg => emit('success', msg),
|
||||
error: msg => emit('error', msg),
|
||||
showValidationErrors,
|
||||
showResponseError,
|
||||
};
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
*/
|
||||
class Translator {
|
||||
|
||||
/**
|
||||
* Create an instance, Passing in the required translations
|
||||
* @param translations
|
||||
*/
|
||||
constructor(translations) {
|
||||
constructor() {
|
||||
this.store = new Map();
|
||||
this.parseTranslations();
|
||||
}
|
||||
|
@ -27,7 +23,7 @@ class Translator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a translation, Same format as laravel's 'trans' helper
|
||||
* Get a translation, Same format as Laravel's 'trans' helper
|
||||
* @param key
|
||||
* @param replacements
|
||||
* @returns {*}
|
||||
|
@ -38,8 +34,8 @@ class Translator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get pluralised text, Dependant on the given count.
|
||||
* Same format at laravel's 'trans_choice' helper.
|
||||
* Get pluralised text, Dependent on the given count.
|
||||
* Same format at Laravel's 'trans_choice' helper.
|
||||
* @param key
|
||||
* @param count
|
||||
* @param replacements
|
||||
|
@ -52,7 +48,7 @@ class Translator {
|
|||
|
||||
/**
|
||||
* Parse the given translation and find the correct plural option
|
||||
* to use. Similar format at laravel's 'trans_choice' helper.
|
||||
* to use. Similar format at Laravel's 'trans_choice' helper.
|
||||
* @param {String} translation
|
||||
* @param {Number} count
|
||||
* @param {Object} replacements
|
||||
|
@ -117,14 +113,17 @@ class Translator {
|
|||
*/
|
||||
performReplacements(string, replacements) {
|
||||
if (!replacements) return string;
|
||||
const replaceMatches = string.match(/:([\S]+)/g);
|
||||
const replaceMatches = string.match(/:(\S+)/g);
|
||||
if (replaceMatches === null) return string;
|
||||
let updatedString = string;
|
||||
|
||||
replaceMatches.forEach(match => {
|
||||
const key = match.substring(1);
|
||||
if (typeof replacements[key] === 'undefined') return;
|
||||
string = string.replace(match, replacements[key]);
|
||||
updatedString = updatedString.replace(match, replacements[key]);
|
||||
});
|
||||
return string;
|
||||
|
||||
return updatedString;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import DrawIO from '../services/drawio';
|
||||
import * as DrawIO from '../services/drawio';
|
||||
|
||||
let pageEditor = null;
|
||||
let currentNode = null;
|
||||
|
|
Loading…
Reference in New Issue
Block a user