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('')); + } 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 = '
    1. '; + 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 = '
    1. '; + 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 @@
  • +
  • + +
    +
    +