mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-19 22:03:19 +03:00
120 lines
3.0 KiB
JavaScript
120 lines
3.0 KiB
JavaScript
import DialogBox from "./DialogBox";
|
|
import DialogForm from "./DialogForm";
|
|
import DialogInput from "./DialogInput";
|
|
import DialogRadioOptions from "./DialogRadioOptions";
|
|
import schema from "../schema";
|
|
|
|
import {MenuItem} from "./menu";
|
|
import {icons} from "./icons";
|
|
import {expandSelectionToMark, nullifyEmptyValues} from "../util";
|
|
|
|
/**
|
|
* @param {PmMarkType} markType
|
|
* @param {String} attribute
|
|
* @return {(function(PmEditorState): (string|null))}
|
|
*/
|
|
function getMarkAttribute(markType, attribute) {
|
|
return function (state) {
|
|
const marks = state.selection.$head.marks();
|
|
for (const mark of marks) {
|
|
if (mark.type === markType) {
|
|
return mark.attrs[attribute];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {(function(FormData))} submitter
|
|
* @param {Function} closer
|
|
* @return {DialogBox}
|
|
*/
|
|
function getLinkDialog(submitter, closer) {
|
|
return new DialogBox([
|
|
new DialogForm([
|
|
new DialogInput({
|
|
label: 'URL',
|
|
id: 'href',
|
|
value: getMarkAttribute(schema.marks.link, 'href'),
|
|
}),
|
|
new DialogInput({
|
|
label: 'Hover Label',
|
|
id: 'title',
|
|
value: getMarkAttribute(schema.marks.link, 'title'),
|
|
}),
|
|
new DialogRadioOptions({
|
|
"Same tab or window": "",
|
|
"New tab or window": "_blank",
|
|
}, {
|
|
label: 'Behaviour',
|
|
id: 'target',
|
|
value: getMarkAttribute(schema.marks.link, 'target'),
|
|
})
|
|
], {
|
|
canceler: closer,
|
|
action: submitter,
|
|
}),
|
|
], {
|
|
label: 'Insert Link',
|
|
closer: closer,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {FormData} formData
|
|
* @param {PmEditorState} state
|
|
* @param {PmDispatchFunction} dispatch
|
|
* @return {boolean}
|
|
*/
|
|
function applyLink(formData, state, dispatch) {
|
|
const selection = state.selection;
|
|
const attrs = nullifyEmptyValues(Object.fromEntries(formData));
|
|
if (!dispatch) return true;
|
|
|
|
const tr = state.tr;
|
|
const {from, to} = expandSelectionToMark(state, selection, schema.marks.link);
|
|
|
|
if (attrs.href) {
|
|
tr.addMark(from, to, schema.marks.link.create(attrs));
|
|
} else {
|
|
tr.removeMark(from, to, schema.marks.link);
|
|
}
|
|
|
|
dispatch(tr);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param {PmEditorState} state
|
|
* @param {PmDispatchFunction} dispatch
|
|
* @param {PmView} view
|
|
* @param {Event} e
|
|
*/
|
|
function onPress(state, dispatch, view, e) {
|
|
const dialog = getLinkDialog((data) => {
|
|
applyLink(data, state, dispatch);
|
|
dom.remove();
|
|
}, () => {
|
|
dom.remove();
|
|
})
|
|
|
|
const {dom, update} = dialog.render(view);
|
|
update(state);
|
|
document.body.appendChild(dom);
|
|
}
|
|
|
|
/**
|
|
* @return {MenuItem}
|
|
*/
|
|
function anchorButtonItem() {
|
|
return new MenuItem({
|
|
title: "Insert/Edit Anchor Link",
|
|
run: onPress,
|
|
enable: state => true,
|
|
icon: icons.link,
|
|
});
|
|
}
|
|
|
|
export default anchorButtonItem; |