export const replaceText = (markdownName, textToChange) => {
let editedText;
switch (markdownName) {
case 'Strikethrough':
editedText = `~~${textToChange}~~`;
break;
case 'Bold':
editedText = `**${textToChange}**`;
break;
case 'Italic':
editedText = `_${textToChange}_`;
break;
case 'Underline':
editedText = `${textToChange}`;
break;
case 'Code':
editedText = `\`\`\`\n${textToChange}\n\`\`\``;
break;
case 'Link':
editedText = `[${textToChange}](link)`;
break;
case 'Quote':
editedText = `>${textToChange}`;
break;
default:
editedText = textToChange;
}
return editedText;
};
export const insertText = (markdownName) => {
let editedText;
// object to calculate text that will be selected after insert of markdown
let selection = { start: markdownName.length, end: 0 };
switch (markdownName) {
case 'Strikethrough':
editedText = `~~${markdownName}~~`;
selection.end = 2;
break;
case 'Bold':
editedText = `**${markdownName}**`;
selection.end = 2;
break;
case 'Italic':
editedText = `_${markdownName}_`;
selection.end = 1;
break;
case 'alt':
editedText = `[${markdownName}]()`;
selection.end = 3;
break;
case 'Underline':
editedText = `${markdownName}`;
selection.end = 4;
break;
case 'Code':
editedText = `\`\`\`\n${markdownName}\n\`\`\``;
selection.end = 3;
break;
case 'Link':
editedText = `[${markdownName}](link)`;
selection.end = 7;
break;
case 'Quote':
editedText = `>${markdownName}`;
selection.end = 0;
break;
default:
editedText = '';
}
return { editedText, selection };
};
export const insertListOrTitle = (markdown) => {
let textToInsert;
switch (markdown) {
case 'BulletList':
textToInsert = '- ';
break;
case 'NumberList':
textToInsert = '1. ';
break;
case 'h1':
textToInsert = '# ';
break;
case 'h2':
textToInsert = '## ';
break;
case 'h3':
textToInsert = '### ';
break;
case 'h4':
textToInsert = '#### ';
break;
case 'h5':
textToInsert = '##### ';
break;
case 'h6':
textToInsert = '###### ';
break;
default:
return '';
}
return textToInsert;
};
// EDITOR ACTIONS FUNCTIONS
export const markdownHandler = (editor, markdownType) => {
const textToEdit = editor.current.getSelection();
let textToInsert;
if (textToEdit) {
const editedText = replaceText(markdownType, textToEdit);
editor.current.replaceSelection(editedText);
editor.current.focus();
} else {
textToInsert = insertText(markdownType);
editor.current.replaceSelection(textToInsert.editedText);
editor.current.focus();
// set selection-focus to text to replace with content
const { line, ch } = editor.current.getCursor();
const endSelection = ch - textToInsert.selection.end;
const startSelection = ch - textToInsert.selection.end - textToInsert.selection.start;
editor.current.setSelection({ line, ch: startSelection }, { line, ch: endSelection });
}
};
export const listHandler = (editor, listType) => {
const doc = editor.current.getDoc();
const insertion = listType === 'BulletList' ? '- ' : '1. ';
if (doc.somethingSelected()) {
const selections = doc.listSelections();
let remove = null;
editor.current.operation(function () {
selections.forEach(function (selection) {
const pos = [selection.head.line, selection.anchor.line].sort();
// Remove if the first text starts with it
if (remove == null) {
remove = doc.getLine(pos[0]).startsWith(insertion);
}
for (let i = pos[0]; i <= pos[1]; i++) {
if (remove) {
// Don't remove if we don't start with it
if (doc.getLine(i).startsWith(insertion)) {
doc.replaceRange('', { line: i, ch: 0 }, { line: i, ch: insertion.length });
}
} else {
const lineInsertion = listType === 'BulletList' ? '- ' : `${i + 1}. `;
doc.replaceRange(lineInsertion, { line: i, ch: 0 });
}
}
});
});
} else {
let { line: currentLine } = doc.getCursor();
const listToInsert = insertListOrTitle(listType);
const lineContent = editor.current.getLine(currentLine);
const textToInsert = listToInsert + lineContent;
editor.current.setSelection(
{ line: currentLine, ch: 0 },
{ line: currentLine, ch: lineContent.length }
);
editor.current.replaceSelection(textToInsert);
}
editor.current.focus();
};
export const titleHandler = (editor, titleType) => {
let { line: currentLine } = editor.current.getCursor();
const titleToInsert = insertListOrTitle(titleType);
const lineContent = editor.current.getLine(currentLine);
// replace hashtags followed by a space in case user want to change the type of title
const lineWithNoTitle = lineContent.replace(/#{1,6}\s/g, '').trim();
const textToInsert = titleToInsert + lineWithNoTitle;
editor.current.setSelection(
{ line: currentLine, ch: 0 },
{ line: currentLine, ch: lineContent.length }
);
editor.current.replaceSelection(textToInsert);
setTimeout(() => {
const newLastLineLength = editor.current.getLine(currentLine).length;
editor.current.focus();
editor.current.setCursor({ line: currentLine, ch: newLastLineLength });
}, 0);
};
export const insertFile = (editor, files) => {
let { line, ch } = editor.current.getCursor();
files.forEach((file, i) => {
let contentLength = editor.current.getLine(line).length;
editor.current.setCursor({ line, ch: contentLength });
// create a new line after first image markdown inserted
// or if there is content in current line
if (i > 0 || (i === 0 && ch !== 0)) {
contentLength = editor.current.getLine(line).length;
editor.current.setCursor({ line, ch: contentLength });
line++;
editor.current.replaceSelection('\n');
}
if (file.mime.includes('image')) {
editor.current.replaceSelection(``);
} else {
editor.current.replaceSelection(`[${file.alt}](${file.url})`);
}
});
setTimeout(() => editor.current.focus(), 0);
};
// NEXT FUNCTIONS FOR QUOTE OR CODE MARKDOWN
const insertWithTextToEdit = (editor, markdownType, line, contentLength, textToEdit) => {
const textToInsert = replaceText(markdownType, textToEdit);
// remove content after current line
const contentToMove = editor.current.getRange(
{ line: line + 1, ch: 0 },
{ line: Infinity, ch: Infinity }
);
editor.current.replaceRange('', { line: line + 1, ch: 0 }, { line: Infinity, ch: Infinity });
// remove word that was selected
// set cursor end of line + move to next line
// add text to insert
editor.current.replaceSelection('');
editor.current.setCursor({ line, ch: contentLength });
editor.current.replaceSelection('\n');
editor.current.replaceSelection(textToInsert);
if (markdownType === 'Code') {
let { line: newLine } = editor.current.getCursor();
editor.current.setCursor({ line: newLine - 1, ch: textToEdit.length });
}
// add content we had to remove earlier
editor.current.replaceRange(
contentToMove,
{ line: line + 4, ch: 0 },
{ line: Infinity, ch: Infinity }
);
editor.current.focus();
};
const insertWithoutTextToEdit = (editor, markdownType, line, contentLength) => {
const textToInsert = insertText(markdownType);
// remove content after current line
const contentToMove = editor.current.getRange(
{ line: line + 1, ch: 0 },
{ line: Infinity, ch: Infinity }
);
editor.current.replaceRange('', { line: line + 1, ch: 0 }, { line: Infinity, ch: Infinity });
// replace cursor to next line
editor.current.setCursor({ line, ch: contentLength });
editor.current.replaceSelection('\n');
editor.current.replaceSelection(textToInsert.editedText);
// set selection on "Code" or "Quote" word
if (markdownType === 'Code') {
line += 2;
editor.current.setSelection({ line, ch: 0 }, { line, ch: 4 });
} else {
line += 1;
let { ch } = editor.current.getCursor();
let endSelection = ch - textToInsert.selection.end;
let startSelection = ch - textToInsert.selection.end - textToInsert.selection.start;
editor.current.setSelection({ line, ch: startSelection }, { line, ch: endSelection });
}
// add content we had to remove earlier
editor.current.replaceRange(
contentToMove,
{ line: line + 2, ch: 0 },
{ line: Infinity, ch: Infinity }
);
editor.current.focus();
};
export const quoteAndCodeHandler = (editor, markdownType) => {
const textToEdit = editor.current.getSelection();
let { line } = editor.current.getCursor();
let contentLength = editor.current.getLine(line).length;
if (textToEdit) {
insertWithTextToEdit(editor, markdownType, line, contentLength, textToEdit);
} else {
insertWithoutTextToEdit(editor, markdownType, line, contentLength);
}
};