diff --git a/node/utils/ExportHtml.js b/node/utils/ExportHtml.js
index c699c4119..d4be80d20 100644
--- a/node/utils/ExportHtml.js
+++ b/node/utils/ExportHtml.js
@@ -309,13 +309,14 @@ function getHTMLFromAtext(pad, atext)
// People might use weird indenting, e.g. skip a level,
// so we want to do something reasonable there. We also
// want to deal gracefully with blank lines.
+ // => keeps track of the parents level of indentation
var lists = []; // e.g. [[1,'bullet'], [3,'bullet'], ...]
for (var i = 0; i < textLines.length; i++)
{
var line = _analyzeLine(textLines[i], attribLines[i], apool);
var lineContent = getLineHTML(line.text, line.aline);
-
- if (line.listLevel || lists.length > 0)
+
+ if (line.listLevel)//If we are inside a list
{
// do list stuff
var whichList = -1; // index into lists or -1
@@ -331,41 +332,89 @@ function getHTMLFromAtext(pad, atext)
}
}
- if (whichList >= lists.length)
+ if (whichList >= lists.length)//means we are on a deeper level of indentation than the previous line
{
lists.push([line.listLevel, line.listTypeName]);
- pieces.push('
- ', lineContent || '
');
+ if(line.listTypeName == "number")
+ {
+ pieces.push('- ', lineContent || '
');
+ }
+ else
+ {
+ pieces.push('- ', lineContent || '
');
+ }
}
- else if (whichList == -1)
+ //the following code *seems* dead after my patch.
+ //I keep it just in case I'm wrong...
+ /*else if (whichList == -1)//means we are not inside a list
{
if (line.text)
{
+ console.log('trace 1');
// non-blank line, end all lists
- pieces.push(new Array(lists.length + 1).join('
'));
+ if(line.listTypeName == "number")
+ {
+ pieces.push(new Array(lists.length + 1).join('
'));
+ }
+ else
+ {
+ pieces.push(new Array(lists.length + 1).join('
'));
+ }
lists.length = 0;
pieces.push(lineContent, '
');
}
else
{
+ console.log('trace 2');
pieces.push('
');
}
- }
- else
+ }*/
+ else//means we are getting closer to the lowest level of indentation
{
while (whichList < lists.length - 1)
{
- pieces.push('');
+ if(lists[lists.length - 1][1] == "number")
+ {
+ pieces.push('');
+ }
+ else
+ {
+ pieces.push('');
+ }
lists.length--;
}
pieces.push('', lineContent || '
');
}
}
- else
+ else//outside any list
{
+ while (lists.length > 0)//if was in a list: close it before
+ {
+ if(lists[lists.length - 1][1] == "number")
+ {
+ pieces.push('');
+ }
+ else
+ {
+ pieces.push('');
+ }
+ lists.length--;
+ }
pieces.push(lineContent, '
');
}
}
- pieces.push(new Array(lists.length + 1).join(''));
+
+ for (var k = lists.length - 1; k >= 0; k--)
+ {
+ if(lists[k][1] == "number")
+ {
+ pieces.push('');
+ }
+ else
+ {
+ pieces.push('');
+ }
+ }
return pieces.join('');
}
@@ -415,7 +464,24 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
{
if(ERR(err, callback)) return;
- var head = (noDocType ? '' : '\n') + '\n' + (noDocType ? '' : '\n' + '\n' + '\n' + '\n') + '';
+ var head =
+ (noDocType ? '' : '\n') +
+ '\n' + (noDocType ? '' : '\n' +
+ '\n' +
+ '\n' + '\n') +
+ '';
var foot = '\n\n';
diff --git a/node/utils/contentcollector.js b/node/utils/contentcollector.js
index 60bd0a6ef..a7fa940a6 100644
--- a/node/utils/contentcollector.js
+++ b/node/utils/contentcollector.js
@@ -472,10 +472,10 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
{
cc.doAttrib(state, "strikethrough");
}
- if (tname == "ul")
+ if (tname == "ul" || tname == "ol")
{
var type;
- var rr = cls && /(?:^| )list-(bullet[12345678])\b/.exec(cls);
+ var rr = cls && /(?:^| )list-([a-z]+[12345678])\b/.exec(cls);
type = rr && rr[1] || "bullet" + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1));
oldListTypeOrNull = (_enterList(state, type) || 'none');
}
diff --git a/static/css/iframe_editor.css b/static/css/iframe_editor.css
index 86ca99117..2faaae065 100644
--- a/static/css/iframe_editor.css
+++ b/static/css/iframe_editor.css
@@ -32,6 +32,25 @@ ul.list-bullet6 { list-style-type: square; }
ul.list-bullet7 { list-style-type: disc; }
ul.list-bullet8 { list-style-type: circle; }
+ol.list-number1 { margin-left: 1.5em; }
+ol.list-number2 { margin-left: 3em; }
+ol.list-number3 { margin-left: 4.5em; }
+ol.list-number4 { margin-left: 6em; }
+ol.list-number5 { margin-left: 7.5em; }
+ol.list-number6 { margin-left: 9em; }
+ol.list-number7 { margin-left: 10.5em; }
+ol.list-number8 { margin-left: 12em; }
+
+ol { list-style-type: decimal; }
+ol.list-number1 { list-style-type: decimal; }
+ol.list-number2 { list-style-type: lower-latin; }
+ol.list-number3 { list-style-type: lower-roman; }
+ol.list-number4 { list-style-type: decimal; }
+ol.list-number5 { list-style-type: lower-latin; }
+ol.list-number6 { list-style-type: lower-roman; }
+ol.list-number7 { list-style-type: decimal; }
+ol.list-number8 { list-style-type: lower-latin; }
+
ul.list-indent1 { margin-left: 1.5em; }
ul.list-indent2 { margin-left: 3em; }
ul.list-indent3 { margin-left: 4.5em; }
@@ -74,7 +93,7 @@ body.doesWrap {
padding-top: 1px; /* important for some reason? */
padding-right: 10px;
padding-bottom: 8px;
- padding-left: 1px /* prevents characters from looking chopped off in FF3 */;
+ padding-left: 10px /* prevents characters from looking chopped off in FF3 */;
overflow: hidden;
/* blank 1x1 gif, so that IE8 doesn't consider the body transparent */
background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==);
diff --git a/static/css/pad.css b/static/css/pad.css
index 41ef75902..feed00e44 100644
--- a/static/css/pad.css
+++ b/static/css/pad.css
@@ -1069,6 +1069,10 @@ position: relative;
background-position: 0px -459px;
}
+#exportdokuwiki{
+ background-position: 2px -144px;
+}
+
#export a{
text-decoration: none;
}
diff --git a/static/css/timeslider.css b/static/css/timeslider.css
index e34509322..9df408683 100644
--- a/static/css/timeslider.css
+++ b/static/css/timeslider.css
@@ -221,3 +221,40 @@ ul.list-bullet6 { list-style-type: square; }
ul.list-bullet7 { list-style-type: disc; }
ul.list-bullet8 { list-style-type: circle; }
+ol.list-number1 { margin-left: 1.5em; }
+ol.list-number2 { margin-left: 3em; }
+ol.list-number3 { margin-left: 4.5em; }
+ol.list-number4 { margin-left: 6em; }
+ol.list-number5 { margin-left: 7.5em; }
+ol.list-number6 { margin-left: 9em; }
+ol.list-number7 { margin-left: 10.5em; }
+ol.list-number8 { margin-left: 12em; }
+
+ol { list-style-type: decimal; }
+ol.list-number1 { list-style-type: decimal; }
+ol.list-number2 { list-style-type: lower-latin; }
+ol.list-number3 { list-style-type: lower-roman; }
+ol.list-number4 { list-style-type: decimal; }
+ol.list-number5 { list-style-type: lower-latin; }
+ol.list-number6 { list-style-type: lower-roman; }
+ol.list-number7 { list-style-type: decimal; }
+ol.list-number8 { list-style-type: lower-latin; }
+
+ul.list-indent1 { margin-left: 1.5em; }
+ul.list-indent2 { margin-left: 3em; }
+ul.list-indent3 { margin-left: 4.5em; }
+ul.list-indent4 { margin-left: 6em; }
+ul.list-indent5 { margin-left: 7.5em; }
+ul.list-indent6 { margin-left: 9em; }
+ul.list-indent7 { margin-left: 10.5em; }
+ul.list-indent8 { margin-left: 12em; }
+
+ul.list-indent1 { list-style-type: none; }
+ul.list-indent2 { list-style-type: none; }
+ul.list-indent3 { list-style-type: none; }
+ul.list-indent4 { list-style-type: none; }
+ul.list-indent5 { list-style-type: none; }
+ul.list-indent6 { list-style-type: none; }
+ul.list-indent7 { list-style-type: none; }
+ul.list-indent8 { list-style-type: none; }
+
diff --git a/static/img/fileicons.gif b/static/img/fileicons.gif
new file mode 100644
index 000000000..c03b6031a
Binary files /dev/null and b/static/img/fileicons.gif differ
diff --git a/static/js/ace2_inner.js b/static/js/ace2_inner.js
index bad0ca346..15c6debae 100644
--- a/static/js/ace2_inner.js
+++ b/static/js/ace2_inner.js
@@ -3535,16 +3535,36 @@ function OUTER(gscope)
var lineNum = rep.selStart[0];
var listType = getLineListType(lineNum);
- performDocumentReplaceSelection('\n');
if (listType)
{
- if (lineNum + 1 < rep.lines.length())
+ var text = rep.lines.atIndex(lineNum).text;
+ listType = /([a-z]+)([12345678])/.exec(listType);
+ var type = listType[1];
+ var level = Number(listType[2]);
+
+ //detect empty list item; exclude indentation
+ if(text === '*' && type !== "indent")
{
- setLineListType(lineNum + 1, listType);
+ //if not already on the highest level
+ if(level > 1)
+ {
+ setLineListType(lineNum, type+(level-1));//automatically decrease the level
+ }
+ else
+ {
+ setLineListType(lineNum, '');//remove the list
+ renumberList(lineNum + 1);//trigger renumbering of list that may be right after
+ }
+ }
+ else if (lineNum + 1 < rep.lines.length())
+ {
+ performDocumentReplaceSelection('\n');
+ setLineListType(lineNum + 1, type+level);
}
}
else
{
+ performDocumentReplaceSelection('\n');
handleReturnIndentation();
}
}
@@ -3688,6 +3708,15 @@ function OUTER(gscope)
}
}
}
+ //if the list has been removed, it is necessary to renumber
+ //starting from the *next* line because the list may have been
+ //separated. If it returns null, it means that the list was not cut, try
+ //from the current one.
+ var line = caretLine();
+ if(line != -1 && renumberList(line+1)==null)
+ {
+ renumberList(line);
+ }
}
// set of "letter or digit" chars is based on section 20.5.16 of the original Java Language Spec
@@ -5184,7 +5213,83 @@ function OUTER(gscope)
[lineNum, listType]
]);
}
-
+
+ function renumberList(lineNum){
+ //1-check we are in a list
+ var type = getLineListType(lineNum);
+ if(!type)
+ {
+ return null;
+ }
+ type = /([a-z]+)[12345678]/.exec(type);
+ if(type[1] == "indent")
+ {
+ return null;
+ }
+
+ //2-find the first line of the list
+ while(lineNum-1 >= 0 && (type=getLineListType(lineNum-1)))
+ {
+ type = /([a-z]+)[12345678]/.exec(type);
+ if(type[1] == "indent")
+ break;
+ lineNum--;
+ }
+
+ //3-renumber every list item of the same level from the beginning, level 1
+ //IMPORTANT: never skip a level because there imbrication may be arbitrary
+ var builder = Changeset.builder(rep.lines.totalWidth());
+ loc = [0,0];
+ function applyNumberList(line, level)
+ {
+ //init
+ var position = 1;
+ var curLevel = level;
+ var listType;
+ //loop over the lines
+ while(listType = getLineListType(line))
+ {
+ //apply new num
+ listType = /([a-z]+)([12345678])/.exec(listType);
+ curLevel = Number(listType[2]);
+ if(isNaN(curLevel) || listType[0] == "indent")
+ {
+ return line;
+ }
+ else if(curLevel == level)
+ {
+ buildKeepRange(builder, loc, (loc = [line, 0]));
+ buildKeepRange(builder, loc, (loc = [line, 1]), [
+ ['start', position]
+ ], rep.apool);
+
+ position++;
+ line++;
+ }
+ else if(curLevel < level)
+ {
+ return line;//back to parent
+ }
+ else
+ {
+ line = applyNumberList(line, level+1);//recursive call
+ }
+ }
+ return line;
+ }
+
+ applyNumberList(lineNum, 1);
+ var cs = builder.toString();
+ if (!Changeset.isIdentity(cs))
+ {
+ performDocumentApplyChangeset(cs);
+ }
+
+ //4-apply the modifications
+
+
+ }
+
function setLineListTypes(lineNumTypePairsInOrder)
{
var loc = [0, 0];
@@ -5231,9 +5336,18 @@ function OUTER(gscope)
{
performDocumentApplyChangeset(cs);
}
+
+ //if the list has been removed, it is necessary to renumber
+ //starting from the *next* line because the list may have been
+ //separated. If it returns null, it means that the list was not cut, try
+ //from the current one.
+ if(renumberList(lineNum+1)==null)
+ {
+ renumberList(lineNum);
+ }
}
- function doInsertUnorderedList()
+ function doInsertList(type)
{
if (!(rep.selStart && rep.selEnd))
{
@@ -5248,7 +5362,7 @@ function OUTER(gscope)
for (var n = firstLine; n <= lastLine; n++)
{
var listType = getLineListType(n);
- if (!listType || listType.slice(0, 'bullet'.length) != 'bullet')
+ if (!listType || listType.slice(0, type.length) != type)
{
allLinesAreList = false;
break;
@@ -5267,11 +5381,19 @@ function OUTER(gscope)
level = Number(listType[2]);
}
var t = getLineListType(n);
- mods.push([n, allLinesAreList ? 'indent' + level : (t ? 'bullet' + level : 'bullet1')]);
+ mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]);
}
setLineListTypes(mods);
}
+
+ function doInsertUnorderedList(){
+ doInsertList('bullet');
+ }
+ function doInsertOrderedList(){
+ doInsertList('number');
+ }
editorInfo.ace_doInsertUnorderedList = doInsertUnorderedList;
+ editorInfo.ace_doInsertOrderedList = doInsertOrderedList;
var mozillaFakeArrows = (browser.mozilla && (function()
{
diff --git a/static/js/contentcollector.js b/static/js/contentcollector.js
index 69036ba25..883ca09f0 100644
--- a/static/js/contentcollector.js
+++ b/static/js/contentcollector.js
@@ -476,7 +476,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
{
cc.doAttrib(state, "strikethrough");
}
- if (tname == "ul")
+ if (tname == "ul" || tname == "ol")
{
var type;
var rr = cls && /(?:^| )list-([a-z]+[12345678])\b/.exec(cls);
diff --git a/static/js/domline.js b/static/js/domline.js
index 3456419c4..84aeb4a81 100644
--- a/static/js/domline.js
+++ b/static/js/domline.js
@@ -95,13 +95,23 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
if (cls.indexOf('list') >= 0)
{
var listType = /(?:^| )list:(\S+)/.exec(cls);
+ var start = /(?:^| )start:(\S+)/.exec(cls);
if (listType)
{
listType = listType[1];
+ start = start?'start="'+start[1]+'"':'';
if (listType)
{
- preHtml = '';
+ if(listType.indexOf("number") < 0)
+ {
+ preHtml = '';
+ }
+ else
+ {
+ preHtml = '- ';
+ postHtml = '
';
+ }
}
result.lineMarker += txt.length;
return; // don't append any text
diff --git a/static/js/domline_client.js b/static/js/domline_client.js
index cac753b96..9f47dae54 100644
--- a/static/js/domline_client.js
+++ b/static/js/domline_client.js
@@ -94,13 +94,23 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
if (cls.indexOf('list') >= 0)
{
var listType = /(?:^| )list:(\S+)/.exec(cls);
+ var start = /(?:^| )start:(\S+)/.exec(cls);
if (listType)
{
listType = listType[1];
+ start = start?'start="'+start[1]+'"':'';
if (listType)
{
- preHtml = '';
+ if(listType.indexOf("number") < 0)
+ {
+ preHtml = '';
+ }
+ else
+ {
+ preHtml = '- ';
+ postHtml = '
';
+ }
}
result.lineMarker += txt.length;
return; // don't append any text
@@ -141,8 +151,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
plugins_.callHook("aceCreateDomLine", {
domline: domline,
- cls: cls,
- document: document
+ cls: cls
}).map(function(modifier)
{
cls = modifier.cls;
@@ -158,7 +167,11 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
{
if (href)
{
- extraOpenTags = extraOpenTags + '';
+ if(!~href.indexOf("http")) // if the url doesn't include http or https etc prefix it.
+ {
+ href = "http://"+href;
+ }
+ extraOpenTags = extraOpenTags + '';
extraCloseTags = '' + extraCloseTags;
}
if (simpleTags)
diff --git a/static/js/linestylefilter.js b/static/js/linestylefilter.js
index 9164d42f0..13a746186 100644
--- a/static/js/linestylefilter.js
+++ b/static/js/linestylefilter.js
@@ -90,6 +90,10 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
{
classes += ' list:' + value;
}
+ else if (key == 'start')
+ {
+ classes += ' start:' + value;
+ }
else if (linestylefilter.ATTRIB_CLASSES[key])
{
classes += ' ' + linestylefilter.ATTRIB_CLASSES[key];
diff --git a/static/js/linestylefilter_client.js b/static/js/linestylefilter_client.js
index 69c3f1242..9fd2a3f8c 100644
--- a/static/js/linestylefilter_client.js
+++ b/static/js/linestylefilter_client.js
@@ -88,6 +88,10 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
{
classes += ' list:' + value;
}
+ else if (key == 'start')
+ {
+ classes += ' start:' + value;
+ }
else if (linestylefilter.ATTRIB_CLASSES[key])
{
classes += ' ' + linestylefilter.ATTRIB_CLASSES[key];
@@ -241,7 +245,7 @@ linestylefilter.getRegexpFilter = function(regExp, tag)
linestylefilter.REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
linestylefilter.REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/\\?=()$]/.source + '|' + linestylefilter.REGEX_WORDCHAR.source + ')');
-linestylefilter.REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt):\/\/|mailto:)/.source + linestylefilter.REGEX_URLCHAR.source + '*(?![:.,;])' + linestylefilter.REGEX_URLCHAR.source, 'g');
+linestylefilter.REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt):\/\/|mailto:|www\.)/.source + linestylefilter.REGEX_URLCHAR.source + '*(?![:.,;])' + linestylefilter.REGEX_URLCHAR.source, 'g');
linestylefilter.getURLFilter = linestylefilter.getRegexpFilter(
linestylefilter.REGEX_URL, 'url');
diff --git a/static/js/pad_editbar.js b/static/js/pad_editbar.js
index b4b4c1cca..6cd5163de 100644
--- a/static/js/pad_editbar.js
+++ b/static/js/pad_editbar.js
@@ -126,6 +126,7 @@ var padeditbar = (function()
if (cmd == 'bold' || cmd == 'italic' || cmd == 'underline' || cmd == 'strikethrough') ace.ace_toggleAttributeOnSelection(cmd);
else if (cmd == 'undo' || cmd == 'redo') ace.ace_doUndoRedo(cmd);
else if (cmd == 'insertunorderedlist') ace.ace_doInsertUnorderedList();
+ else if (cmd == 'insertorderedlist') ace.ace_doInsertOrderedList();
else if (cmd == 'indent')
{
if (!ace.ace_doIndentOutdent(false))
diff --git a/static/pad.html b/static/pad.html
index c6fd3e774..5c68f7733 100644
--- a/static/pad.html
+++ b/static/pad.html
@@ -46,6 +46,11 @@
+
+
+
+
+