You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by br...@apache.org on 2019/03/09 20:25:55 UTC
[jspwiki] branch master updated: 2.11.0-M3-git-02: editor drag&drop
capabilities
This is an automated email from the ASF dual-hosted git repository.
brushed pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jspwiki.git
The following commit(s) were added to refs/heads/master by this push:
new b69256a 2.11.0-M3-git-02: editor drag&drop capabilities
b69256a is described below
commit b69256a48d2b2e781f41a42c39e1602121ff0b47
Author: brushed <di...@gmail.com>
AuthorDate: Sat Mar 9 21:25:44 2019 +0100
2.11.0-M3-git-02: editor drag&drop capabilities
---
ChangeLog | 9 +
.../src/main/java/org/apache/wiki/Release.java | 2 +-
jspwiki-war/src/main/config/wro/wro-haddock.xml | 5 +-
jspwiki-war/src/main/config/wro/wro.properties | 1 +
.../src/main/scripts/moo-extend/Textarea.js | 59 +++++-
.../src/main/scripts/wiki-edit/Html2Wiki.js | 227 +++++++++++++++++++++
jspwiki-war/src/main/scripts/wiki-edit/Snipe.js | 11 +-
.../src/main/scripts/wiki-edit/Wiki.Edit.js | 27 ++-
.../src/main/styles/haddock/default/type.less | 3 +-
9 files changed, 323 insertions(+), 21 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index d71fa6c..a9d326b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2019-03-09 Dirk Frederickx (brushed AT apache DOT org)
+ * 2.11.0-M3-git-02
+
+ * Adding Drag & Drop capabilities to the standard JSPWiki editor:
+ links automatically are converted to [descriptiol|url] format
+ other content (text, tables, etc...) will be converted to wiki-markup.
+
+
+2019-03-09 Dirk Frederickx (brushed AT apache DOT org)
+
* 2.11.0-M3-git-01
* UserPreferences fixes
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/Release.java b/jspwiki-main/src/main/java/org/apache/wiki/Release.java
index 96f5860..602abbf 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/Release.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/Release.java
@@ -72,7 +72,7 @@ public final class Release {
* <p>
* If the build identifier is empty, it is not added.
*/
- public static final String BUILD = "01";
+ public static final String BUILD = "02";
/**
* This is the generic version string you should use when printing out the version. It is of
diff --git a/jspwiki-war/src/main/config/wro/wro-haddock.xml b/jspwiki-war/src/main/config/wro/wro-haddock.xml
index 7cb0ccf..623698d 100644
--- a/jspwiki-war/src/main/config/wro/wro-haddock.xml
+++ b/jspwiki-war/src/main/config/wro/wro-haddock.xml
@@ -32,10 +32,10 @@
<js>/scripts/moo-extend/Function.Extend.js</js>
<js>/scripts/moo-extend/Behavior.js</js>
<js>/scripts/moo-extend/String.Extend.js</js>
+ <!--<js>/scripts/moo-extend/Date.Extend.js</js>-->
<js>/scripts/moo-extend/Array.Extend.js</js>
<js>/scripts/moo-extend/Array.NaturalSort.js</js>
<js>/scripts/moo-extend/Element.Extend.js</js>
- <js>/scripts/moo-extend/Element.Placeholder.js</js>
<js>/scripts/moo-extend/Color.js</js>
<js>/scripts/moo-extend/HighlightQuery.js</js>
<js>/scripts/moo-extend/Accesskey.js</js>
@@ -67,7 +67,6 @@
</group>
<group name="haddock">
-
<group-ref>lib</group-ref>
<group-ref>mooextend</group-ref>
<group-ref>behaviors</group-ref>
@@ -92,7 +91,6 @@
</group>
<group name="haddock-edit">
-
<js>/scripts/moo-extend/Date.Extend.js</js>
<js>/scripts/moo-extend/Array.Extend.HSV.js</js>
@@ -105,6 +103,7 @@
<js>/scripts/dialog/Dialog.Find.js</js>
<js>/scripts/moo-extend/Textarea.js</js>
+ <js>/scripts/wiki-edit/Html2Wiki.js</js>
<js>/scripts/wiki-edit/Undoable.js</js>
<js>/scripts/wiki-edit/Snipe.js</js>
<js>/scripts/wiki-edit/Snipe.Snips.js</js>
diff --git a/jspwiki-war/src/main/config/wro/wro.properties b/jspwiki-war/src/main/config/wro/wro.properties
index 7c810dc..fdf5c5a 100644
--- a/jspwiki-war/src/main/config/wro/wro.properties
+++ b/jspwiki-war/src/main/config/wro/wro.properties
@@ -23,3 +23,4 @@ debug=true
preProcessors=cssImport,semicolonAppender
#postProcessors=lessCss,yuiCssMin,uglifyJs
postProcessors=less4j,yuiCssMin,uglifyJs
+
diff --git a/jspwiki-war/src/main/scripts/moo-extend/Textarea.js b/jspwiki-war/src/main/scripts/moo-extend/Textarea.js
index 3b084bb..3b36cc5 100644
--- a/jspwiki-war/src/main/scripts/moo-extend/Textarea.js
+++ b/jspwiki-war/src/main/scripts/moo-extend/Textarea.js
@@ -18,10 +18,13 @@
specific language governing permissions and limitations
under the License.
*/
+
/*eslint-env browser*/
/*global Class, Options, Events */
/*exported Textarea */
+/*exported Textarea */
+
/*
Class: Textarea
The textarea class enriches a TEXTAREA element, and provides cross browser
@@ -43,11 +46,8 @@ var Textarea = new Class({
initialize: function(el, options){
var self = this,
- ta = self.ta = document.id(el),
- fireChange = function( event ){
- console.log('hi');
- self.fireEvent("change", event);
- };
+ ta = self.ta = document.id(el);
+ //fireChange = function( event ){ self.fireEvent("change", event); };
self.setOptions(options);
@@ -369,9 +369,56 @@ var Textarea = new Class({
w = el.offsetWidth;
h = el.offsetHeight;
- console.log(offset, ta.offsetTop, "top: "+t, ta.offsetLeft, "left: "+l, "width: "+w, "height: "+h, "right: "+(l + w), "bottom: "+(t + h) );
+ //console.log(offset, ta.offsetTop, "top: "+t, ta.offsetLeft, "left: "+l, "width: "+w, "height: "+h, "right: "+(l + w), "bottom: "+(t + h) );
return { top: t, left: l, width: w, height: h, right: l + w, bottom: t + h };
+ },
+
+
+ /*
+ Function: onDragAndDrop
+ Add Drag&Drop handlers on the Textarea
+ Inspired by https://github.com/github/paste-markdown
+
+ */
+ onDragAndDrop: function(processData, onSuccess){
+
+ var self = this,
+ ta = this.ta;
+
+ ta.addEventListener('dragover', function(event /*DragEvent*/){
+
+ var dataTransfer = event.dataTransfer;
+ if (dataTransfer){ dataTransfer.dropEffect = 'copy'; }
+ });
+
+ ta.addEventListener('drop', function(event /*DragEvent*/){
+
+ var dataTransfer = event.dataTransfer;
+ if (dataTransfer && (dataTransfer.files.length == 0)){
+ insertData(event, dataTransfer);
+ }
+ });
+
+ ta.addEventListener('paste', function(event /*ClipboardEvent*/){
+
+ insertData(event, event.clipboardData);
+ });
+
+ function insertData(event, dataTransfer){
+
+ var content = processData(dataTransfer);
+
+ if ( content ) {
+
+ event.stopPropagation();
+ event.preventDefault();
+ self.insertAfter(content);
+
+ if( onSuccess ){ onSuccess(); }
+ }
+ }
}
+
});
diff --git a/jspwiki-war/src/main/scripts/wiki-edit/Html2Wiki.js b/jspwiki-war/src/main/scripts/wiki-edit/Html2Wiki.js
new file mode 100644
index 0000000..7afa0d4
--- /dev/null
+++ b/jspwiki-war/src/main/scripts/wiki-edit/Html2Wiki.js
@@ -0,0 +1,227 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); fyou may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/*eslint-env browser*/
+/*global Wiki*/
+
+/*
+Html2Wiki
+ Mini html to wiki markup convertor for JSPWiki.
+ Used by the Wiki.Edit.js to handle html which is input via drap&drop, or copy&paste.
+
+ It uses a brute-force find&replace approach, rather then a fine-grained walk the dome tree approach.
+ It gets the job done 90% of the time.
+
+*/
+!(function( wiki, document ){
+
+ //convert url to wiki link
+ wiki.url2links = function( links ){
+
+ return links ? links.split("\r\n").map(function(link){
+
+ return "\n[" + link + "]\n";
+
+ }) : links;
+
+ }
+
+ //convert html to wiki-markup
+ wiki.html2wiki = function( html ){
+
+ if( !html ) return;
+
+ //console.log(html);
+
+ //make temporary dom element to convert html to wiki markup
+ var dom = "div".slick({html:html});
+
+ forEachTextNode(dom, /\[/g, "[["); //url's in text nodes are converted to [link]
+ forEachNode(dom, "style", removeElement);
+
+ //inline elements
+ substituteEachNode(dom, "b,strong", "__{0}__" );
+ substituteEachNode(dom, "i", "''{0}''" );
+ substituteEachNode(dom, "sup", "%%sup {0}/%");
+ substituteEachNode(dom, "sub", "%%sub {0}/%");
+ forEachNode(dom, "a", replaceHtmlA);
+ substituteEachNode(dom, "tt", "{{{0}}}" );
+ substituteEachNode(dom, "pre,code", "\n{{{\n{0}\n}}}\n" );
+
+ //block elements
+ substituteEachNode(dom, "hr", "\n----\n");
+ substituteEachNode(dom, "br", " \\\\ ");
+ substituteEachNode(dom, "h1,h2", "\n!!! {0}\n");
+ substituteEachNode(dom, "h3", "\n!! {0}\n");
+ substituteEachNode(dom, "h4", "\n! {0}\n");
+ substituteEachNode(dom, "dl dt", "\n;{0}:");
+
+ forEachNode(dom, "li", replaceHtmlLI);
+
+ forEachNode(dom, "tr", replaceHtmlTR);
+ substituteEachNode(dom, "p", "\n{0}\n");
+
+ return dom.textContent.replace(/^\s*(.*)\s*$/,"$1")+"\n";
+ }
+
+
+// Helper functions
+/*
+Function: forEachTextNode
+ Iterate over all descendent text nodes and replace their contents.
+
+Example
+ forEachTextNode( document, " ", " " );
+ forEachTextNode( some_node, /\[/g, "[[");
+*/
+function forEachTextNode(node, substrOrHandle, newSubstr){
+
+ var n,
+ isHandle = typeof substrOrHandle === "function",
+ walk = document.createTreeWalker(node, 4 /*NodeFilter.SHOW_TEXT*/, null, false);
+
+ while(( n = walk.nextNode() )){
+ isHandle ? substrOrHandle(n) : replaceTextContent(n, substrOrHandle, newSubstr);
+ }
+ return node;
+}
+
+/*
+Function: forEachNode
+ Loop over each selected node and invoke a function
+
+Example:
+ forEachNode( document, "p p", function(p){ p.className = "nested_par"; });
+*/
+function forEachNode(node, selector, callback){
+
+ ( node.querySelectorAll(selector) || [] ).forEach(callback);
+ return node;
+}
+
+/*
+Function: substituteEachNode
+ Loop over each selected node, and replace it contents.
+ Use paramater "{0}" to refer to the textContent
+
+Example:
+ forEachNode( document, "p", "\n{0}\n");
+*/
+function substituteEachNode(node, selector, pattern){
+
+ return forEachNode(node, selector, function(n){
+ replaceNodeByText(n, pattern.xsubs(n.textContent) );
+ });
+}
+
+/*
+Function: replaceNodeByText
+ Replace a Node by a Text-Node
+*/
+function replaceNodeByText(node, text){
+
+ node.parentNode.replaceChild( document.createTextNode(text), node );
+
+}
+
+/*
+Function: replaceTextContent
+ Replace the content of a node
+
+Example
+ replaceTextContent( some_node, /\[/g, "[[");
+*/
+function replaceTextContent(node, substrOrRegExp, newSubstr){
+
+ node.textContent = node.textContent.replace(substrOrRegExp, newSubstr);
+
+}
+
+/*
+Function: removeElement
+*/
+function removeElement(node){
+
+ node.parentNode.removeChild(node);
+
+}
+
+/*
+Function: getAncestors
+ Return array of all ancestors, matching the selector
+
+Example
+ getAncestors( some_li_element, "ul,ol" );
+*/
+function getAncestors(node, selector){
+
+ var ancestors = [];
+
+ while(( node = node.parentElement )){
+ if( node.matches(selector) ){ ancestors.push(node); }
+ }
+ return ancestors;
+}
+
+
+// Wiki Html-to-Markup helper functions
+
+// convert <a href="...">description</a> into [description|url]
+function replaceHtmlA( link ){
+
+ var href = link.href,
+ description = link.textContent;
+
+ //escape the [ and ] characters inside the link-description text
+ description = description.replace(/\[\[/g,"[").replace(/\]/g,"]");
+
+ replaceNodeByText( link, " [" + description + "|" + href + "] ");
+}
+
+// convert <tr>...</tr> in wiki table rows with a | or || prefix
+function replaceHtmlTR( row ){
+
+ var s = "\n", c, cell;
+
+ for(c=0; (cell = row.cells[c]); c++){
+
+ s += ( cell.tagName.test( /th/i ) ? "||" : "|") +
+ ( cell.textContent.trim() || ' ');
+// ( cell.textContent.trim().replace(/\|/g, '~|') || ' ');
+ }
+ replaceNodeByText(row, s );
+}
+
+// convert <li> in wiki list items with a * or # prefix
+function replaceHtmlLI( li ){
+
+ var listType = li.parentElement.tagName,
+ markup = listType.test(/ul/i) ? "*" : listType.test(/ol/i) ? "#" : "*",
+ depth = getAncestors(li, "ul,ol").length;
+
+ if(( li = li.firstChild )){
+ replaceTextContent(li, /.*/, "\n" + markup.repeat(depth) + " "+ "$&");
+ }
+}
+
+
+})( Wiki, document );
+
diff --git a/jspwiki-war/src/main/scripts/wiki-edit/Snipe.js b/jspwiki-war/src/main/scripts/wiki-edit/Snipe.js
index 61d27c6..ee4edb1 100644
--- a/jspwiki-war/src/main/scripts/wiki-edit/Snipe.js
+++ b/jspwiki-war/src/main/scripts/wiki-edit/Snipe.js
@@ -162,6 +162,15 @@ var Snipe = new Class({
});
+ //add drag&drop handler: drag or paste data into the textarea
+ if( options.dragAndDrop ){
+
+ textarea.onDragAndDrop(options.dragAndDrop, function(){
+ self.fireEvent("change")
+ });
+ }
+
+
self.reset();
element.addEvents({
@@ -708,7 +717,7 @@ var Snipe = new Class({
// match "pfx{selection}sfx" into ["pfx","selection","sfx"]
// do not match "pfx~{do-not-match}sfx"
- if( snipXL = snippet.match( /(^|[\S\s]*[^~])\{([^!\{\}][^\{\}]*)\}([\S\s]*)/ ) ){
+ if(( snipXL = snippet.match( /(^|[\S\s]*[^~])\{([^!{}][^{}]*)\}([\S\s]*)/ ) )){
//if( snipXL = snippet.match( /(^|[\S\s]*[^~])\{([^\{\}]+)\}([\S\s]*)/ ) ){
//console.log("Snipe:action complex snippet 'pfx{selection}sfx' ", pfx, sel, sfx, caret.thin );
diff --git a/jspwiki-war/src/main/scripts/wiki-edit/Wiki.Edit.js b/jspwiki-war/src/main/scripts/wiki-edit/Wiki.Edit.js
index 74a1653..f5a8730 100644
--- a/jspwiki-war/src/main/scripts/wiki-edit/Wiki.Edit.js
+++ b/jspwiki-war/src/main/scripts/wiki-edit/Wiki.Edit.js
@@ -27,7 +27,7 @@ Class: Wiki.Edit
*/
/*eslint-env browser*/
-/*global Wiki, Snipe, Request */
+/*global $, Wiki, Snipe, Request */
!(function( wiki ){
@@ -43,7 +43,7 @@ wiki.add("textarea#editorarea", function( main ){
onbeforeunload( window, main );
- if( snipe = getFormElem("textarea.snipeable") ){
+ if(( snipe = getFormElem("textarea.snipeable") )){
snipe = new Snipe( snipe, {
container: form,
@@ -52,14 +52,15 @@ wiki.add("textarea#editorarea", function( main ){
redo: getFormElem("[data-cmd=redo]")
},
snippets: wiki.Snips,
- directsnips: wiki.DirectSnips
+ directsnips: wiki.DirectSnips,
+ dragAndDrop: processDragAndDropData
});
wiki.configPrefs(form, function(cmd, isChecked){
snipe.set(cmd, isChecked);
});
- if( preview = getFormElem(".ajaxpreview") ){
+ if(( preview = getFormElem(".ajaxpreview") )){
var snipeHasChanged = false;
@@ -105,7 +106,7 @@ wiki.add("textarea#editorarea", function( main ){
}
-}).add("textarea[name=htmlPageText]", function( main){
+}).add("textarea[name=htmlPageText]", function( /*main*/ ){
LocalCache = "wiki" + wiki.PageName;
if(LocalCache in localStorage){
@@ -114,8 +115,6 @@ wiki.add("textarea#editorarea", function( main ){
})
-
-
/*
Function: onbeforeunload
Install an onbeforeunload handler, which is called prior to unloading the page.
@@ -266,7 +265,7 @@ function jspwikiSectionParser( text ){
title = tt[i + 1].split(/[\r\n]/)[0]
//remove unescaped(~) inline wiki markup __,"",{{,}}, %%(*), /%
- .replace(/(^|[^~])(__|""|\{\{|\}\}|%%\([^\)]+\)|%%\S+\s|%%\([^\)]+\)|\/%)/g, "$1")
+ .replace(/(^|[^~])(__|""|\{\{|\}\}|%%\([^)]+\)|%%\S+\s|%%\([^)]+\)|\/%)/g, "$1")
//and remove wiki-markup escape chars ~
.replace(/~([^~])/g, "$1");
@@ -281,6 +280,18 @@ function jspwikiSectionParser( text ){
}
+/*
+Function
+ Call back handler, invoked when data is dragged or copied into the editor textarea.
+ Call Html2Wiki.js to process the incoming data & convert to wiki markup
+
+*/
+function processDragAndDropData( dataTransfer ){
+
+ return wiki.url2links( dataTransfer.getData('text/uri-list') )
+ || wiki.html2wiki( dataTransfer.getData('text/html') );
+
+}
})( Wiki );
diff --git a/jspwiki-war/src/main/styles/haddock/default/type.less b/jspwiki-war/src/main/styles/haddock/default/type.less
index 55b33d6..0c83ac8 100644
--- a/jspwiki-war/src/main/styles/haddock/default/type.less
+++ b/jspwiki-war/src/main/styles/haddock/default/type.less
@@ -57,11 +57,10 @@ DOM structure:
.editsection, .hashlink {
.btn; .btn-default; .btn-xs;
- line-height:1;
margin-right: .25em;
.transition(all 1s ease);
&:hover { .opacity(1); border-color:transparent; }
-
+ user-select:none;
}
h2,h3,h4 {