Ordered list support

This commit is contained in:
John McLear 2012-01-15 17:20:20 +00:00
parent c45932c6b8
commit f4dca37a93
14 changed files with 316 additions and 31 deletions

View file

@ -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('<ul><li>', lineContent || '<br>');
if(line.listTypeName == "number")
{
pieces.push('<ol class="'+line.listTypeName+'"><li>', lineContent || '<br>');
}
else
{
pieces.push('<ul class="'+line.listTypeName+'"><li>', lineContent || '<br>');
}
}
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('</li></ul\n>'));
if(line.listTypeName == "number")
{
pieces.push(new Array(lists.length + 1).join('</li></ol>'));
}
else
{
pieces.push(new Array(lists.length + 1).join('</li></ul>'));
}
lists.length = 0;
pieces.push(lineContent, '<br>');
}
else
{
console.log('trace 2');
pieces.push('<br><br>');
}
}
else
}*/
else//means we are getting closer to the lowest level of indentation
{
while (whichList < lists.length - 1)
{
pieces.push('</li></ul>');
if(lists[lists.length - 1][1] == "number")
{
pieces.push('</li></ol>');
}
else
{
pieces.push('</li></ul>');
}
lists.length--;
}
pieces.push('</li><li>', lineContent || '<br>');
}
}
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('</li></ol>');
}
else
{
pieces.push('</li></ul>');
}
lists.length--;
}
pieces.push(lineContent, '<br>');
}
}
pieces.push(new Array(lists.length + 1).join('</li></ul>'));
for (var k = lists.length - 1; k >= 0; k--)
{
if(lists[k][1] == "number")
{
pieces.push('</li></ol>');
}
else
{
pieces.push('</li></ul>');
}
}
return pieces.join('');
}
@ -415,7 +464,24 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
{
if(ERR(err, callback)) return;
var head = (noDocType ? '' : '<!doctype html>\n') + '<html lang="en">\n' + (noDocType ? '' : '<head>\n' + '<meta charset="utf-8">\n' + '<style> * { font-family: arial, sans-serif;\n' + 'font-size: 13px;\n' + 'line-height: 17px; }</style>\n' + '</head>\n') + '<body>';
var head =
(noDocType ? '' : '<!doctype html>\n') +
'<html lang="en">\n' + (noDocType ? '' : '<head>\n' +
'<meta charset="utf-8">\n' +
'<style> * { font-family: arial, sans-serif;\n' +
'font-size: 13px;\n' +
'line-height: 17px; }' +
'ul.indent { list-style-type: none; }' +
'ol { list-style-type: decimal; }' +
'ol ol { list-style-type: lower-latin; }' +
'ol ol ol { list-style-type: lower-roman; }' +
'ol ol ol ol { list-style-type: decimal; }' +
'ol ol ol ol ol { list-style-type: lower-latin; }' +
'ol ol ol ol ol ol{ list-style-type: lower-roman; }' +
'ol ol ol ol ol ol ol { list-style-type: decimal; }' +
'ol ol ol ol ol ol ol ol{ list-style-type: lower-latin; }' +
'</style>\n' + '</head>\n') +
'<body>';
var foot = '</body>\n</html>\n';

View file

@ -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');
}

View file

@ -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==);

View file

@ -1069,6 +1069,10 @@ position: relative;
background-position: 0px -459px;
}
#exportdokuwiki{
background-position: 2px -144px;
}
#export a{
text-decoration: none;
}

View file

@ -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; }

BIN
static/img/fileicons.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -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()
{

View file

@ -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);

View file

@ -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 = '<ul class="list-' + listType + '"><li>';
postHtml = '</li></ul>';
if(listType.indexOf("number") < 0)
{
preHtml = '<ul class="list-' + listType + '"><li>';
postHtml = '</li></ul>';
}
else
{
preHtml = '<ol '+start+' class="list-' + listType + '"><li>';
postHtml = '</li></ol>';
}
}
result.lineMarker += txt.length;
return; // don't append any text

View file

@ -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 = '<ul class="list-' + listType + '"><li>';
postHtml = '</li></ul>';
if(listType.indexOf("number") < 0)
{
preHtml = '<ul class="list-' + listType + '"><li>';
postHtml = '</li></ul>';
}
else
{
preHtml = '<ol '+start+' class="list-' + listType + '"><li>';
postHtml = '</li></ol>';
}
}
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 + '<a href="' + domline.escapeHTML(href) + '">';
if(!~href.indexOf("http")) // if the url doesn't include http or https etc prefix it.
{
href = "http://"+href;
}
extraOpenTags = extraOpenTags + '<a href="' + href.replace(/\"/g, '&quot;') + '">';
extraCloseTags = '</a>' + extraCloseTags;
}
if (simpleTags)

View file

@ -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];

View file

@ -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');

View file

@ -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))

View file

@ -46,6 +46,11 @@
</a>
</li>
<li class="separator"></li>
<li onClick="window.pad&amp;&amp;pad.editbarClick('insertorderedlist');return false;" >
<a title="Toggle Ordered List">
<div class="buttonicon" style="background-position:0px -436px"></div>
</a>
</li>
<li onClick="window.pad&amp;&amp;pad.editbarClick('insertunorderedlist');return false;" >
<a title="Toggle Bullet List">
<div class="buttonicon" style="background-position:0px -34px"></div>