mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #5213 from open-sausages/pulls/4.0/fix-tinymce-shortcodes
API and BUG fix; Update ssbuttons tinymce plugin for image shortcode parsing
This commit is contained in:
commit
3573236310
@ -32,7 +32,7 @@ HtmlEditorConfig::get('cms')
|
||||
->enablePlugins(array(
|
||||
'contextmenu' => null,
|
||||
'image' => null,
|
||||
'ssbuttons' => THIRDPARTY_DIR . '/tinymce_ssbuttons/plugin.min.js'
|
||||
'ssbuttons' => FRAMEWORK_DIR . '/javascript/dist/TinyMCE_SSPlugin.js'
|
||||
));
|
||||
|
||||
CMSMenu::remove_menu_item('CMSProfileController');
|
||||
|
23
gulpfile.js
23
gulpfile.js
@ -20,7 +20,7 @@ var gulp = require('gulp'),
|
||||
sprity = require('sprity'),
|
||||
gulpif = require('gulp-if'),
|
||||
sourcemaps = require('gulp-sourcemaps');
|
||||
|
||||
|
||||
var isDev = typeof process.env.npm_config_development !== 'undefined';
|
||||
|
||||
var PATHS = {
|
||||
@ -273,27 +273,6 @@ gulp.task('thirdparty', function () {
|
||||
copyFiles(blueimpTmplConfig);
|
||||
copyFiles(jquerySizesConfig);
|
||||
copyFiles(tinymceConfig);
|
||||
|
||||
// TODO Remove once all TinyMCE plugins are bundled
|
||||
var stream = browserify(Object.assign({}, browserifyOptions, {
|
||||
entries: PATHS.FRAMEWORK_THIRDPARTY + '/tinymce_ssbuttons/plugin.js'
|
||||
}))
|
||||
.transform(babelify.configure({
|
||||
presets: ['es2015'],
|
||||
comments: false
|
||||
}))
|
||||
.bundle()
|
||||
.on('error', notify.onError({
|
||||
message: 'Error: <%= error.message %>',
|
||||
}))
|
||||
.pipe(source('plugin.min.js'))
|
||||
.pipe(buffer());
|
||||
|
||||
if (!isDev) {
|
||||
stream.pipe(uglify());
|
||||
}
|
||||
|
||||
return stream.pipe(gulp.dest(PATHS.FRAMEWORK_THIRDPARTY + '/tinymce_ssbuttons/'));
|
||||
});
|
||||
|
||||
gulp.task('umd', ['umd-admin', 'umd-framework']);
|
||||
|
173
javascript/dist/TinyMCE_SSPlugin.js
vendored
Normal file
173
javascript/dist/TinyMCE_SSPlugin.js
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define('ss.TinyMCE_SSPlugin', [], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory();
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory();
|
||||
global.ssTinyMCE_SSPlugin = mod.exports;
|
||||
}
|
||||
})(this, function () {
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
|
||||
var ssbuttons = {
|
||||
getInfo: function getInfo() {
|
||||
return {
|
||||
longname: 'Special buttons for SilverStripe CMS',
|
||||
author: 'Sam Minnée',
|
||||
authorurl: 'http://www.siverstripe.com/',
|
||||
infourl: 'http://www.silverstripe.com/',
|
||||
version: "1.0"
|
||||
};
|
||||
},
|
||||
|
||||
init: function init(ed) {
|
||||
ed.addButton('sslink', {
|
||||
icon: 'link',
|
||||
title: 'Insert Link',
|
||||
cmd: 'sslink'
|
||||
});
|
||||
ed.addMenuItem('sslink', {
|
||||
icon: 'link',
|
||||
text: 'Insert Link',
|
||||
cmd: 'sslink'
|
||||
});
|
||||
ed.addButton('ssmedia', {
|
||||
icon: 'image',
|
||||
title: 'Insert Media',
|
||||
cmd: 'ssmedia'
|
||||
});
|
||||
ed.addMenuItem('ssmedia', {
|
||||
icon: 'image',
|
||||
text: 'Insert Media',
|
||||
cmd: 'ssmedia'
|
||||
});
|
||||
|
||||
ed.addCommand('sslink', function (ed) {
|
||||
jQuery('#' + this.id).entwine('ss').openLinkDialog();
|
||||
});
|
||||
|
||||
ed.addCommand('ssmedia', function (ed) {
|
||||
jQuery('#' + this.id).entwine('ss').openMediaDialog();
|
||||
});
|
||||
|
||||
ed.on('BeforeExecCommand', function (e) {
|
||||
var cmd = e.command;
|
||||
var ui = e.ui;
|
||||
var val = e.value;
|
||||
if (cmd == 'mceAdvLink' || cmd == 'mceLink') {
|
||||
e.preventDefault();
|
||||
ed.execCommand('sslink', ui, val);
|
||||
} else if (cmd == 'mceAdvImage' || cmd == 'mceImage') {
|
||||
e.preventDefault();
|
||||
ed.execCommand('ssmedia', ui, val);
|
||||
}
|
||||
});
|
||||
|
||||
ed.on('SaveContent', function (o) {
|
||||
var content = jQuery(o.content);
|
||||
var attrsFn = function attrsFn(attrs) {
|
||||
return Object.keys(attrs).map(function (name) {
|
||||
return attrs[name] ? name + '="' + attrs[name] + '"' : null;
|
||||
}).filter(function (el) {
|
||||
return el !== null;
|
||||
}).join(' ');
|
||||
};
|
||||
|
||||
content.find('.ss-htmleditorfield-file.embed').each(function () {
|
||||
var el = jQuery(this);
|
||||
var attrs = {
|
||||
width: el.attr('width'),
|
||||
class: el.attr('cssclass'),
|
||||
thumbnail: el.data('thumbnail')
|
||||
};
|
||||
var shortCode = '[embed ' + attrsFn(attrs) + ']' + el.data('url') + '[/embed]';
|
||||
el.replaceWith(shortCode);
|
||||
});
|
||||
|
||||
content.find('img').each(function () {
|
||||
var el = jQuery(this);
|
||||
var attrs = {
|
||||
src: el.attr('src'),
|
||||
id: el.data('id'),
|
||||
width: el.attr('width'),
|
||||
height: el.attr('height'),
|
||||
class: el.attr('class'),
|
||||
|
||||
title: el.attr('title'),
|
||||
alt: el.attr('alt')
|
||||
};
|
||||
var shortCode = '[image ' + attrsFn(attrs) + ']';
|
||||
el.replaceWith(shortCode);
|
||||
});
|
||||
|
||||
o.content = '';
|
||||
content.each(function () {
|
||||
if (this.outerHTML !== undefined) {
|
||||
o.content += this.outerHTML;
|
||||
}
|
||||
});
|
||||
});
|
||||
ed.on('BeforeSetContent', function (o) {
|
||||
var matches;
|
||||
var content = o.content;
|
||||
var attrFromStrFn = function attrFromStrFn(str) {
|
||||
return str.match(/([^\s\/'"=,]+)\s*=\s*(('([^']+)')|("([^"]+)")|([^\s,\]]+))/g).reduce(function (coll, val) {
|
||||
var match = val.match(/^([^\s\/'"=,]+)\s*=\s*(?:(?:'([^']+)')|(?:"([^"]+)")|(?:[^\s,\]]+))$/),
|
||||
key = match[1],
|
||||
value = match[2] || match[3] || match[4];
|
||||
coll[key] = value;
|
||||
return coll;
|
||||
}, {});
|
||||
};
|
||||
|
||||
var shortTagRegex = /\[embed(.*?)\](.+?)\[\/\s*embed\s*\]/gi;
|
||||
while (matches = shortTagRegex.exec(content)) {
|
||||
var attrs = attrFromStrFn(matches[1]);
|
||||
var el;
|
||||
|
||||
el = jQuery('<img/>').attr({
|
||||
'src': attrs['thumbnail'],
|
||||
'width': attrs['width'],
|
||||
'height': attrs['height'],
|
||||
'class': attrs['class'],
|
||||
'data-url': matches[2]
|
||||
}).addClass('ss-htmleditorfield-file embed');
|
||||
attrs['cssclass'] = attrs['class'];
|
||||
|
||||
Object.keys(attrs).forEach(function (key) {
|
||||
return el.attr('data-' + key, attrs[key]);
|
||||
});
|
||||
content = content.replace(matches[0], jQuery('<div/>').append(el).html());
|
||||
}
|
||||
|
||||
var shortTagRegex = /\[image(.*?)\]/gi;
|
||||
while (matches = shortTagRegex.exec(content)) {
|
||||
var attrs = attrFromStrFn(matches[1]);
|
||||
var el = jQuery('<img/>').attr({
|
||||
'src': attrs['src'],
|
||||
'width': attrs['width'],
|
||||
'height': attrs['height'],
|
||||
'class': attrs['class'],
|
||||
'alt': attrs['alt'],
|
||||
'title': attrs['title'],
|
||||
'data-id': attrs['id']
|
||||
});
|
||||
content = content.replace(matches[0], jQuery('<div/>').append(el).html());
|
||||
}
|
||||
|
||||
o.content = content;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
tinymce.PluginManager.add("ssbuttons", function (editor) {
|
||||
ssbuttons.init(editor);
|
||||
});
|
||||
})();
|
||||
});
|
@ -91,7 +91,6 @@
|
||||
content.find('img').each(function() {
|
||||
var el = jQuery(this);
|
||||
var attrs = {
|
||||
// TODO Don't store 'src' since its more volatile than 'id'.
|
||||
// Requires server-side preprocessing of HTML+shortcodes in HTMLValue
|
||||
src: el.attr('src'),
|
||||
id: el.data('id'),
|
||||
@ -121,15 +120,13 @@
|
||||
var content = o.content;
|
||||
var attrFromStrFn = (str) => {
|
||||
return str
|
||||
// Remove quotation marks and trim.
|
||||
.replace(/['"]/g, '')
|
||||
.replace(/(^\s+|\s+$)/g, '')
|
||||
// Extract the attrs and values into a key-value array,
|
||||
// or key-key if no value is set.
|
||||
.split(/\s+/)
|
||||
// Split on all attributes, quoted or not
|
||||
.match(/([^\s\/'"=,]+)\s*=\s*(('([^']+)')|("([^"]+)")|([^\s,\]]+))/g)
|
||||
.reduce((coll, val) => {
|
||||
var pair = val.split('=');
|
||||
coll[pair[0]] = (pair.length == 1) ? pair[0] : pair[1];
|
||||
var match = val.match(/^([^\s\/'"=,]+)\s*=\s*(?:(?:'([^']+)')|(?:"([^"]+)")|(?:[^\s,\]]+))$/),
|
||||
key = match[1],
|
||||
value = match[2] || match[3] || match[4]; // single, double, or unquoted match
|
||||
coll[key] = value;
|
||||
return coll;
|
||||
}, {});
|
||||
};
|
||||
@ -166,8 +163,6 @@
|
||||
'title': attrs['title'],
|
||||
'data-id': attrs['id']
|
||||
});
|
||||
|
||||
Object.keys(attrs).forEach((key) => el.attr('data-' + key, attrs[key]));
|
||||
content = content.replace(matches[0], (jQuery('<div/>').append(el).html()));
|
||||
}
|
||||
|
1
thirdparty/tinymce_ssbuttons/plugin.min.js
vendored
1
thirdparty/tinymce_ssbuttons/plugin.min.js
vendored
@ -1 +0,0 @@
|
||||
!function t(e,n,i){function r(s,c){if(!n[s]){if(!e[s]){var o="function"==typeof require&&require;if(!c&&o)return o(s,!0);if(a)return a(s,!0);var d=new Error("Cannot find module '"+s+"'");throw d.code="MODULE_NOT_FOUND",d}var u=n[s]={exports:{}};e[s][0].call(u.exports,function(t){var n=e[s][1][t];return r(n?n:t)},u,u.exports,t,e,n,i)}return n[s].exports}for(var a="function"==typeof require&&require,s=0;s<i.length;s++)r(i[s]);return r}({1:[function(t,e,n){"use strict";!function(){var t={getInfo:function(){return{longname:"Special buttons for SilverStripe CMS",author:"Sam Minnée",authorurl:"http://www.siverstripe.com/",infourl:"http://www.silverstripe.com/",version:"1.0"}},init:function(t){t.addButton("sslink",{icon:"link",title:"Insert Link",cmd:"sslink"}),t.addMenuItem("sslink",{icon:"link",text:"Insert Link",cmd:"sslink"}),t.addButton("ssmedia",{icon:"image",title:"Insert Media",cmd:"ssmedia"}),t.addMenuItem("ssmedia",{icon:"image",text:"Insert Media",cmd:"ssmedia"}),t.addCommand("sslink",function(t){jQuery("#"+this.id).entwine("ss").openLinkDialog()}),t.addCommand("ssmedia",function(t){jQuery("#"+this.id).entwine("ss").openMediaDialog()}),t.on("BeforeExecCommand",function(e){var n=e.command,i=e.ui,r=e.value;"mceAdvLink"==n||"mceLink"==n?(e.preventDefault(),t.execCommand("sslink",i,r)):"mceAdvImage"!=n&&"mceImage"!=n||(e.preventDefault(),t.execCommand("ssmedia",i,r))}),t.on("SaveContent",function(t){var e=jQuery(t.content),n=function(t){return Object.keys(t).map(function(e){return t[e]?e+'="'+t[e]+'"':null}).filter(function(t){return null!==t}).join(" ")};e.find(".ss-htmleditorfield-file.embed").each(function(){var t=jQuery(this),e={width:t.attr("width"),"class":t.attr("cssclass"),thumbnail:t.data("thumbnail")},i="[embed "+n(e)+"]"+t.data("url")+"[/embed]";t.replaceWith(i)}),e.find("img").each(function(){var t=jQuery(this),e={src:t.attr("src"),id:t.data("id"),width:t.attr("width"),height:t.attr("height"),"class":t.attr("class"),title:t.attr("title"),alt:t.attr("alt")},i="[image "+n(e)+"]";t.replaceWith(i)}),t.content="",e.each(function(){void 0!==this.outerHTML&&(t.content+=this.outerHTML)})}),t.on("BeforeSetContent",function(t){for(var e,n=t.content,i=function(t){return t.replace(/['"]/g,"").replace(/(^\s+|\s+$)/g,"").split(/\s+/).reduce(function(t,e){var n=e.split("=");return t[n[0]]=1==n.length?n[0]:n[1],t},{})},r=/\[embed(.*?)\](.+?)\[\/\s*embed\s*\]/gi;e=r.exec(n);){var a,s=i(e[1]);a=jQuery("<img/>").attr({src:s.thumbnail,width:s.width,height:s.height,"class":s["class"],"data-url":e[2]}).addClass("ss-htmleditorfield-file embed"),s.cssclass=s["class"],Object.keys(s).forEach(function(t){return a.attr("data-"+t,s[t])}),n=n.replace(e[0],jQuery("<div/>").append(a).html())}for(var r=/\[image(.*?)\]/gi;e=r.exec(n);){var s=i(e[1]),a=jQuery("<img/>").attr({src:s.src,width:s.width,height:s.height,"class":s["class"],alt:s.alt,title:s.title,"data-id":s.id});Object.keys(s).forEach(function(t){return a.attr("data-"+t,s[t])}),n=n.replace(e[0],jQuery("<div/>").append(a).html())}t.content=n})}};tinymce.PluginManager.add("ssbuttons",function(e){t.init(e)})}()},{}]},{},[1]);
|
Loading…
Reference in New Issue
Block a user