mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 05:36:00 +00:00
Finished update pass of all md editor actions to cm6
This commit is contained in:
parent
32c765d0c3
commit
6f45d34bf8
@ -296,10 +296,11 @@ export class Actions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
replaceLineStartForOrderedList() {
|
replaceLineStartForOrderedList() {
|
||||||
// TODO
|
const selectionRange = this.#getSelectionRange();
|
||||||
const cursor = this.editor.cm.getCursor();
|
const line = this.editor.cm.state.doc.lineAt(selectionRange.from);
|
||||||
const prevLineContent = this.editor.cm.getLine(cursor.line - 1) || '';
|
const prevLine = this.editor.cm.state.doc.line(line.number - 1);
|
||||||
const listMatch = prevLineContent.match(/^(\s*)(\d)([).])\s/) || [];
|
|
||||||
|
const listMatch = prevLine.text.match(/^(\s*)(\d)([).])\s/) || [];
|
||||||
|
|
||||||
const number = (Number(listMatch[2]) || 0) + 1;
|
const number = (Number(listMatch[2]) || 0) + 1;
|
||||||
const whiteSpace = listMatch[1] || '';
|
const whiteSpace = listMatch[1] || '';
|
||||||
@ -314,37 +315,28 @@ export class Actions {
|
|||||||
* Creates a callout block if none existing, and removes it if cycling past the danger type.
|
* Creates a callout block if none existing, and removes it if cycling past the danger type.
|
||||||
*/
|
*/
|
||||||
cycleCalloutTypeAtSelection() {
|
cycleCalloutTypeAtSelection() {
|
||||||
// TODO
|
const selectionRange = this.#getSelectionRange();
|
||||||
const selectionRange = this.editor.cm.listSelections()[0];
|
const line = this.editor.cm.state.doc.lineAt(selectionRange.from);
|
||||||
const lineContent = this.editor.cm.getLine(selectionRange.anchor.line);
|
|
||||||
const lineLength = lineContent.length;
|
|
||||||
const contentRange = {
|
|
||||||
anchor: {line: selectionRange.anchor.line, ch: 0},
|
|
||||||
head: {line: selectionRange.anchor.line, ch: lineLength},
|
|
||||||
};
|
|
||||||
|
|
||||||
const formats = ['info', 'success', 'warning', 'danger'];
|
const formats = ['info', 'success', 'warning', 'danger'];
|
||||||
const joint = formats.join('|');
|
const joint = formats.join('|');
|
||||||
const regex = new RegExp(`class="((${joint})\\s+callout|callout\\s+(${joint}))"`, 'i');
|
const regex = new RegExp(`class="((${joint})\\s+callout|callout\\s+(${joint}))"`, 'i');
|
||||||
const matches = regex.exec(lineContent);
|
const matches = regex.exec(line.text);
|
||||||
const format = (matches ? (matches[2] || matches[3]) : '').toLowerCase();
|
const format = (matches ? (matches[2] || matches[3]) : '').toLowerCase();
|
||||||
|
|
||||||
if (format === formats[formats.length - 1]) {
|
if (format === formats[formats.length - 1]) {
|
||||||
this.wrapLine(`<p class="callout ${formats[formats.length - 1]}">`, '</p>');
|
this.#wrapLine(`<p class="callout ${formats[formats.length - 1]}">`, '</p>');
|
||||||
} else if (format === '') {
|
} else if (format === '') {
|
||||||
this.wrapLine('<p class="callout info">', '</p>');
|
this.#wrapLine('<p class="callout info">', '</p>');
|
||||||
} else {
|
} else {
|
||||||
const newFormatIndex = formats.indexOf(format) + 1;
|
const newFormatIndex = formats.indexOf(format) + 1;
|
||||||
const newFormat = formats[newFormatIndex];
|
const newFormat = formats[newFormatIndex];
|
||||||
const newContent = lineContent.replace(matches[0], matches[0].replace(format, newFormat));
|
const newContent = line.text.replace(matches[0], matches[0].replace(format, newFormat));
|
||||||
this.editor.cm.replaceRange(newContent, contentRange.anchor, contentRange.head);
|
const lineDiff = newContent.length - line.text.length;
|
||||||
|
this.editor.cm.dispatch({
|
||||||
const chDiff = newContent.length - lineContent.length;
|
changes: {from: line.from, to: line.to, insert: newContent},
|
||||||
selectionRange.anchor.ch += chDiff;
|
selection: {anchor: selectionRange.anchor + lineDiff, head: selectionRange.head + lineDiff},
|
||||||
if (selectionRange.anchor !== selectionRange.head) {
|
});
|
||||||
selectionRange.head.ch += chDiff;
|
|
||||||
}
|
|
||||||
this.editor.cm.setSelection(selectionRange.anchor, selectionRange.head);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,38 +364,43 @@ export class Actions {
|
|||||||
* @param {Number} posX
|
* @param {Number} posX
|
||||||
* @param {Number} posY
|
* @param {Number} posY
|
||||||
*/
|
*/
|
||||||
insertTemplate(templateId, posX, posY) {
|
async insertTemplate(templateId, posX, posY) {
|
||||||
// TODO
|
const cursorPos = this.editor.cm.posAtCoords({x: posX, y: posY}, false);
|
||||||
const cursorPos = this.editor.cm.coordsChar({left: posX, top: posY});
|
const {data} = await window.$http.get(`/templates/${templateId}`);
|
||||||
this.editor.cm.setCursor(cursorPos);
|
const content = data.markdown || data.html;
|
||||||
window.$http.get(`/templates/${templateId}`).then(resp => {
|
this.editor.cm.dispatch({
|
||||||
const content = resp.data.markdown || resp.data.html;
|
changes: {from: cursorPos, to: cursorPos, insert: content},
|
||||||
this.editor.cm.replaceSelection(content);
|
selection: {anchor: cursorPos},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert multiple images from the clipboard.
|
* Insert multiple images from the clipboard from an event at the provided
|
||||||
|
* screen coordinates (Typically form a paste event).
|
||||||
* @param {File[]} images
|
* @param {File[]} images
|
||||||
|
* @param {Number} posX
|
||||||
|
* @param {Number} posY
|
||||||
*/
|
*/
|
||||||
insertClipboardImages(images) {
|
insertClipboardImages(images, posX, posY) {
|
||||||
// TODO
|
const cursorPos = this.editor.cm.posAtCoords({x: posX, y: posY}, false);
|
||||||
const cursorPos = this.editor.cm.coordsChar({left: event.pageX, top: event.pageY});
|
|
||||||
this.editor.cm.setCursor(cursorPos);
|
|
||||||
for (const image of images) {
|
for (const image of images) {
|
||||||
this.#uploadImage(image);
|
this.uploadImage(image, cursorPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle image upload and add image into markdown content
|
* Handle image upload and add image into markdown content
|
||||||
* @param {File} file
|
* @param {File} file
|
||||||
|
* @param {?Number} position
|
||||||
*/
|
*/
|
||||||
#uploadImage(file) {
|
async uploadImage(file, position= null) {
|
||||||
// TODO
|
|
||||||
if (file === null || file.type.indexOf('image') !== 0) return;
|
if (file === null || file.type.indexOf('image') !== 0) return;
|
||||||
let ext = 'png';
|
let ext = 'png';
|
||||||
|
|
||||||
|
if (position === null) {
|
||||||
|
position = this.#getSelectionRange().from;
|
||||||
|
}
|
||||||
|
|
||||||
if (file.name) {
|
if (file.name) {
|
||||||
let fileNameMatches = file.name.match(/\.(.+)$/);
|
let fileNameMatches = file.name.match(/\.(.+)$/);
|
||||||
if (fileNameMatches.length > 1) ext = fileNameMatches[1];
|
if (fileNameMatches.length > 1) ext = fileNameMatches[1];
|
||||||
@ -412,25 +409,26 @@ export class Actions {
|
|||||||
// Insert image into markdown
|
// Insert image into markdown
|
||||||
const id = "image-" + Math.random().toString(16).slice(2);
|
const id = "image-" + Math.random().toString(16).slice(2);
|
||||||
const placeholderImage = window.baseUrl(`/loading.gif#upload${id}`);
|
const placeholderImage = window.baseUrl(`/loading.gif#upload${id}`);
|
||||||
const selectedText = this.editor.cm.getSelection();
|
const placeHolderText = `![](${placeholderImage})`;
|
||||||
const placeHolderText = `![${selectedText}](${placeholderImage})`;
|
this.editor.cm.dispatch({
|
||||||
const cursor = this.editor.cm.getCursor();
|
changes: {from: position, to: position, insert: placeHolderText},
|
||||||
this.editor.cm.replaceSelection(placeHolderText);
|
selection: {anchor: position},
|
||||||
this.editor.cm.setCursor({line: cursor.line, ch: cursor.ch + selectedText.length + 3});
|
});
|
||||||
|
|
||||||
const remoteFilename = "image-" + Date.now() + "." + ext;
|
const remoteFilename = "image-" + Date.now() + "." + ext;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file, remoteFilename);
|
formData.append('file', file, remoteFilename);
|
||||||
formData.append('uploaded_to', this.editor.config.pageId);
|
formData.append('uploaded_to', this.editor.config.pageId);
|
||||||
|
|
||||||
window.$http.post('/images/gallery', formData).then(resp => {
|
try {
|
||||||
const newContent = `[![${selectedText}](${resp.data.thumbs.display})](${resp.data.url})`;
|
const {data} = await window.$http.post('/images/gallery', formData);
|
||||||
|
const newContent = `[![](${data.thumbs.display})](${data.url})`;
|
||||||
this.#findAndReplaceContent(placeHolderText, newContent);
|
this.#findAndReplaceContent(placeHolderText, newContent);
|
||||||
}).catch(err => {
|
} catch (err) {
|
||||||
window.$events.emit('error', this.editor.config.text.imageUploadError);
|
window.$events.emit('error', this.editor.config.text.imageUploadError);
|
||||||
this.#findAndReplaceContent(placeHolderText, selectedText);
|
this.#findAndReplaceContent(placeHolderText, '');
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +25,37 @@ export async function init(editor) {
|
|||||||
|
|
||||||
const domEventHandlers = {
|
const domEventHandlers = {
|
||||||
// Handle scroll to sync display view
|
// Handle scroll to sync display view
|
||||||
scroll: (event) => syncActive && onScrollDebounced(event)
|
scroll: (event) => syncActive && onScrollDebounced(event),
|
||||||
|
// Handle image & content drag n drop
|
||||||
|
drop: (event) => {
|
||||||
|
const templateId = event.dataTransfer.getData('bookstack/template');
|
||||||
|
if (templateId) {
|
||||||
|
event.preventDefault();
|
||||||
|
editor.actions.insertTemplate(templateId, event.pageX, event.pageY);
|
||||||
|
}
|
||||||
|
|
||||||
|
const clipboard = new Clipboard(event.dataTransfer);
|
||||||
|
const clipboardImages = clipboard.getImages();
|
||||||
|
if (clipboardImages.length > 0) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
editor.actions.insertClipboardImages(clipboardImages, event.pageX, event.pageY);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Handle image paste
|
||||||
|
paste: (event) => {
|
||||||
|
const clipboard = new Clipboard(event.clipboardData || event.dataTransfer);
|
||||||
|
|
||||||
|
// Don't handle the event ourselves if no items exist of contains table-looking data
|
||||||
|
if (!clipboard.hasItems() || clipboard.containsTabularData()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const images = clipboard.getImages();
|
||||||
|
for (const image of images) {
|
||||||
|
editor.actions.uploadImage(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cm = Code.markdownEditor(
|
const cm = Code.markdownEditor(
|
||||||
@ -40,42 +70,5 @@ export async function init(editor) {
|
|||||||
// TODO
|
// TODO
|
||||||
// cm.setOption('direction', 'ltr');
|
// cm.setOption('direction', 'ltr');
|
||||||
|
|
||||||
|
|
||||||
// Handle image paste
|
|
||||||
// TODO
|
|
||||||
// cm.on('paste', (cm, event) => {
|
|
||||||
// const clipboard = new Clipboard(event.clipboardData || event.dataTransfer);
|
|
||||||
//
|
|
||||||
// // Don't handle the event ourselves if no items exist of contains table-looking data
|
|
||||||
// if (!clipboard.hasItems() || clipboard.containsTabularData()) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const images = clipboard.getImages();
|
|
||||||
// for (const image of images) {
|
|
||||||
// editor.actions.uploadImage(image);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Handle image & content drag n drop
|
|
||||||
// TODO
|
|
||||||
// cm.on('drop', (cm, event) => {
|
|
||||||
//
|
|
||||||
// const templateId = event.dataTransfer.getData('bookstack/template');
|
|
||||||
// if (templateId) {
|
|
||||||
// event.preventDefault();
|
|
||||||
// editor.actions.insertTemplate(templateId, event.pageX, event.pageY);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const clipboard = new Clipboard(event.dataTransfer);
|
|
||||||
// const clipboardImages = clipboard.getImages();
|
|
||||||
// if (clipboardImages.length > 0) {
|
|
||||||
// event.stopPropagation();
|
|
||||||
// event.preventDefault();
|
|
||||||
// editor.actions.insertClipboardImages(clipboardImages);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// });
|
|
||||||
|
|
||||||
return cm;
|
return cm;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user