-
Notifications
You must be signed in to change notification settings - Fork 79
/
TinyMCE_sslink-file.js
143 lines (123 loc) · 4.19 KB
/
TinyMCE_sslink-file.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* global tinymce, editorIdentifier, ss */
import i18n from 'i18n';
import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar';
import React from 'react';
import ReactDOM from 'react-dom';
import jQuery from 'jquery';
import ShortcodeSerialiser from 'lib/ShortcodeSerialiser';
import InsertMediaModal from 'containers/InsertMediaModal/InsertMediaModal';
import Injector, { loadComponent } from 'lib/Injector';
import * as modalActions from 'state/modal/ModalActions';
const commandName = 'sslinkfile';
// Link to external url
TinyMCEActionRegistrar.addAction(
'sslink',
{
text: i18n._t('AssetAdmin.LINKLABEL_FILE', 'Link to a file'),
// eslint-disable-next-line no-console
onclick: (activeEditor) => activeEditor.execCommand(commandName),
priority: 80
},
editorIdentifier,
).addCommandWithUrlTest(commandName, /^\[file_link/);
const plugin = {
init(editor) {
editor.addCommand(commandName, () => {
const field = jQuery(`#${editor.id}`).entwine('ss');
field.openLinkFileDialog();
});
},
};
const modalId = 'insert-link__dialog-wrapper--file';
const InjectableInsertMediaModal = loadComponent(InsertMediaModal);
jQuery.entwine('ss', ($) => {
$('textarea.htmleditor').entwine({
openLinkFileDialog() {
let dialog = $(`#${modalId}`);
if (!dialog.length) {
dialog = $(`<div id="${modalId}" />`);
$('body').append(dialog);
}
dialog.addClass('insert-link__dialog-wrapper');
dialog.setElement(this);
dialog.open();
},
});
/**
* Assumes that $('.insert-link__dialog-wrapper').entwine({}); is defined for shared functions
*/
$(`.js-injector-boot #${modalId}`).entwine({
renderModal(isOpen) {
// We're updating the redux store from outside react. This is a bit unusual, but it's
// the best way to initialise our modal setting.
const { dispatch } = Injector.reducer.store;
dispatch(modalActions.initFormStack('insert-link', 'admin'));
const handleHide = () => {
dispatch(modalActions.reset());
this.close();
};
const handleInsert = (...args) => this.handleInsert(...args);
const attrs = this.getOriginalAttributes();
const selection = tinymce.activeEditor.selection;
const selectionContent = selection.getContent() || '';
const tagName = selection.getNode().tagName;
const requireLinkText = tagName !== 'A' && selectionContent.trim() === '';
// create/update the react component
ReactDOM.render(
<InjectableInsertMediaModal
isOpen={isOpen}
type="insert-link"
onInsert={handleInsert}
onClosed={handleHide}
title={false}
bodyClassName="modal__dialog"
className="insert-link__dialog-wrapper--internal"
fileAttributes={attrs}
requireLinkText={requireLinkText}
/>,
this[0]
);
},
/**
* @param {Object} data - Posted data
* @return {Object}
*/
buildAttributes(data) {
const shortcode = ShortcodeSerialiser.serialise({
name: 'file_link',
properties: { id: data.ID },
}, true);
// Add anchor
const anchor = data.Anchor && data.Anchor.length ? `#${data.Anchor}` : '';
const href = `${shortcode}${anchor}`;
return {
href,
target: data.TargetBlank ? '_blank' : '',
title: data.Description,
};
},
getOriginalAttributes() {
const editor = this.getElement().getEditor();
const node = $(editor.getSelectedNode());
// Get href
const hrefParts = (node.attr('href') || '').split('#');
if (!hrefParts[0]) {
return {};
}
// check if file is safe
const shortcode = ShortcodeSerialiser.match('file_link', false, hrefParts[0]);
if (!shortcode) {
return {};
}
return {
ID: shortcode.properties.id ? parseInt(shortcode.properties.id, 10) : 0,
Anchor: hrefParts[1] || '',
Description: node.attr('title'),
TargetBlank: !!node.attr('target'),
};
},
});
});
// Adds the plugin class to the list of available TinyMCE plugins
tinymce.PluginManager.add(commandName, (editor) => plugin.init(editor));
export default plugin;