I'm using this hack for some time now...
It's a nodelet hack which automatically transforms my wiki-ish syntax into monk-code on submit.
This is done transparently because after a reload the monk-code in the textarea is translated back to the original wiki syntax.
Please note that you can still safely use and blend PM-markup as long as you use lowercase characters. The automatically transformed code is always uppercase.
The biggest benefit is that paragraphs <P> are automatically included between two newlines...
...but I added some more goodies over the years. (see examples further down.)
To activate this for yourself you just need to include the following code into your free nodelet.
<script src='?abspart=1;displaytype=displaycode;node_id=1153804;part=3'></script>
(UPDATE: Additionally the "Free Nodelet" must be activated at Nodelet Settings)
I hope the mechanism of the code is obvious enough to be adapted to your needs.
// create toggle for wiki feature // document.writeln('<form name="wiki"><input type="checkbox" name="on +">wiki?</form><br>'); var textarea=get_textarea(); var form_elements = textarea.form.elements; form_elements[form_elements.length-1].outerHTML += '<span><input type= +"checkbox" name="wiki_on"> <a href="?node_id=1153804">*Wiki?*</a> </s +pan>'; if ( textarea ) { // activate wikifeature //document.forms.wiki.elements.on.checked=true; form_elements.wiki_on.checked=true; } var text; /* expand wiki code to monk code with capital letters */ var info = { 'version': 1.161, 'was' : {}, 'is' : {}, 'start' : "<"+"!-- Wiki2Monks ", 'end' : " --"+">", 'extract': function (text) { var text_new = text.replace(new RegExp( this.start + '(.*?)' + + this.end + '$' ) ,''); if ( text_new.length != text.length) { // match var JSONs = RegExp.$1.split(this.start); // too many st +rings ? var JSON_str = JSONs[JSONs.length-1]; // take last o +ne // console.log( (text.length - text_new.length ) + ">"+ JS +ON_str +"<" ); if (! JSON_str) { JSON_str = {}; } if (JSON) { this.was = JSON.parse(JSON_str); // console.log("Info was: "); // console.log(this.was); } } else { this.was ={}; } return text_new; }, 'inject' : function (text) { text += this.start + this.get_new() + this.end; return text; }, 'get_new' : function() { var is = this.was; is.version = this.version; var str = '{}'; if (JSON ) { // is.JSON = true; str = JSON.stringify(is); } else { // backup for older browsers str = '{"version":' + is.version + ', "JSON": false }'; } this.is = is; return str; } }; function wiki2monks () { //old document.forms.wiki.elements.on.checked if ( textarea && form_elements.wiki_on.checked ) { text=textarea.value; // constants regex var singleword = '\\S+' ; var singleline = '\\S|\\S.*?\\S' ; //******* protect special areas text = init_exclusions(text); text = exclude_all(text); //******* Replace Inline Markup //*** normalize newlines text=text.replace(/\r\n/g,'\n'); // IE sucks! //****** complete lines but excluded //*** > quotes -> <I> > ... </I> text=text.replace(/(^|^\n|\n\n)(> )([^]*?)(?=\n\n|\n$|$)/g,'$1 +<I>> $3</I>'); // quote //*** autolinks to modules, pragmas, cpan text=text.replace(/(\s)(\w+::\w[\w:]*)(\s)/g,link_module); //*** links to perldoc perldoc.perl.org/perlsyn.html#Loop-Cont +rol // -> [HTTP(S)://perldoc.perl.org/perlsyn.html +#Loop-Control|perlsyn#Loop-Control] text=text.replace( /(^|\s)(http(s?):\/\/)(perldoc.perl.org)(\/.*?)?\/(\w+ +).html(#.*?)?(\s|$)/g, '$1[HTTP$3://$4$5/$6.html$7|$6$7]$8' ); //*** internal links http(s)://www.perlmonks.org/?node_id=7087 +38 -> [ID://...] text=text.replace( /(^|\s)(https?:\/\/)(www\.)?perlmonks\.(org|net|com)\/ +(?:index\.pl)?\?node_id=(\d+)(\|.*?)?(\s|$)/g, '$1[ID://$5$6]$7' ); //*** autolinks for remaining http(s)://u.r.l.s text=text.replace( /(^|\s)(http(s?):\/\/)(\S*?)(\s|$)/g, '$1[HTTP$3://$4]$5' ); //*** 'inline code' -> '...' around_words('inline code', 'C', "'", singleline); text = exclude_all(text); // protect new code areas //*** ?documentation? -> [DOC://...] text=text.replace(/(\s)\?(\S+)\?(\s)/g,'$1[DOC://$2|<tt>$2</tt +>]$3'); text = exclude_all(text); // protect new doc areas //*** emphasizer * / _ -> <B><I><U> around_words('bold', 'B', '*', singleline); around_words('italic', 'I', '/', singleline); around_words('underline', 'U', '_', singleline); /* //*** emphasizer * / _ -> <B><I><U> around_words('bold', 'B', '*', singleword); around_words('italic', 'I', '/', singleword); around_words('underline', 'U', '_', singleword); */ //*** \n=== headlines -> <H6>...</H6> text = heading(text); //*** - list items -> <LI>...</LI> // paragraphs starting with (-)+ = (un)orderd text=text.replace(/(\n)(\n-\s+[^]*?)(\n\n)/g,'$1<UL\>$2\n<\/UL +\>\n'); // bullets unordered text=text.replace(/(\n)(\n\+\s+[^]*?)(\n\n)/g,'$1<OL\>$2\n<\/O +L\>\n'); // bullets ordered text=text.replace(/^(\-|\+)(\s+.*?)$/gm,'<LI\>$2'); // bullets + (simple) //*** paragraph text=text.replace(/(\n\n+)/g,'<P\>$1'); // p +aragraph //****** reinclude protected areas text = include_all(text); //*** insert info as html comment (version and so on) text = info.inject(text); textarea.value=text; } // return false; } /* replace words surrounded by wikitags with pm markup eg " *words* " -> " <B>words</B> " */ function around_words ( doc, monk_tag, wiki_tag, inner_re) { var empty = '(^|\\s|$)'; var marker = '(\\' + wiki_tag + ')'; var inner_grp = '(' + inner_re + ')'; var regex = new RegExp( empty + marker + inner_grp + marker + + empty, 'g'); var pre_tag = '<' + monk_tag + '>'; var post_tag = '</' + monk_tag + '>'; var substitute = '$1' + pre_tag + '$3' + post_tag + '$5'; // console.log(doc,regex,substitute); text=text.replace( regex, substitute); } function around_paragraph ( doc, monk_tag, wiki_tag, inner_re) { //stub } /* transform headlines (both ways) eg "^=== text" <-> <H5>text</H5> */ function heading (text,revert) { var maps =[ ['===', 'H5'], ['==' , 'H4'], ['=' , 'H3'], ]; if (revert) { for (var i=maps.length-1; i>=0 ;i--) { var map=maps[i]; var tag0 = new RegExp( '<'+ map[1] + '>','g'); text=text.replace(tag0,map[0]); var tag1 = new RegExp( '</'+ map[1] + '>','g'); text=text.replace(tag1,''); } } else { for (var i=0; i<maps.length;i++) { var map=maps[i]; var from = new RegExp( '^(' +map[0]+ ')(\\s.*?)$','gm'); var to = '<'+ map[1] + '>$2</' + map[1] +'>'; // console.log(from + ' -> ' + to); text=text.replace(from,to); } } return text; } /* revert PM markup back to wiki markup */ function monks2wiki () { //old document.forms.wiki.elements.on.checked if ( textarea && form_elements.wiki_on.checked ) { var text=textarea.value; text = info.extract(text); // protect areas like code sections text = exclude_all(text); // delete <P> text=text.replace(/<P>/g,''); // no quote text=text.replace(/(^|\n\n)<I>(> )([^]*?)<\/I>(?=\n\n|$)/g, +'$1> $3'); // revert around word markup text=text.replace(/<\/?I>/g,'/'); text=text.replace(/<\/?B>/g,'*'); text=text.replace(/<\/?U>/g,'_'); // revert listitems text=text.replace(/<LI>/g,'-'); text=text.replace(/<\/?(U|O)L>/g,''); // revert <H3>..<H5> text = heading(text,1); // reinclude protected areas text = include_all(text); // revert ' (was protected) text=text.replace(/<\/?C>/g,"'"); textarea.value=text; } } function link_module(match, pre, name, post, offset, string) { var core_modules = { 'B::Deparse' : 1, }; var protokoll= core_modules[name] ? 'doc' : 'metamod'; return pre+'['+protokoll.toUpperCase()+'://'+name+']'+post; } (function (){ var DBG=false; var counter=0; // var matches = []; var exclusions = []; var delim="\0"; var delim0=delim+"<<"; var delim1=">>"+delim; init_exclusions =function (text) { exclusions = []; counter=0; text = exclude(text,new RegExp(delim+"+","g"),"delim"); return text; } exclude_all = function (text){ text = exclude(text,/<(c|code)>[^]*?<\/\1>/gi, " +code" ); text = exclude(text,/<(blockquote)>[^]*?<\/\1>/gi, " +blockquote" ); text = exclude(text,/<(pre)>[^]*?<\/\1>/gi, " +pre" ); text = exclude(text,/\[(\w+):\/\/.*?\]/g, " +link" ); // hide <nowiki> as <!--nowiki--> from display text = text.replace(/<(\/?nowiki)>/g, "<!--$1-->") ; text = exclude(text,/<!--nowiki-->[^]*?<!--\/nowiki-->/gi, " +nowiki" ); text = exclude(text,/<\w+\s+.+?>/g, " +innertag" ); text = exclude(text,new RegExp("<"+"!--[^]*?--"+">","g"), " +comment" ); if (DBG) console.log(exclusions); return text; } function exclude(text,pattern,name){ var text_out=text; var match; while (match = pattern.exec(text)) { // if (DBG) console.log(match); var substring = match[0]; var placeholder = name.toUpperCase(); if (match[1]) placeholder += "_"+match[1]; placeholder = delim0 + placeholder + "_" +counter + delim1 +; text_out = text_out.replace( substring, placeholder ); // matches[counter] = substring; exclusions.push( [placeholder,substring] ); counter++; } return text_out; } include_all = function (text){ var exclusion; while ( exclusion = exclusions.pop() ){ var placeholder = exclusion[0]; var substring = exclusion[1]; substring = substring.replace(/\$/g,'$$$$'); // escape $ t +o avoid interpolation text = text.replace( placeholder, substring ); } return text; } })(); /* textareas meant for posting discussions have names ending on '_doct +ext' */ function get_textarea() { var T=document.getElementsByTagName("textarea"); for (var i in T) { var n=T[i].name ; if (n && n.match(/_doctext$/)) return T[i]; } } if (textarea) { // after pageload revert upercase PM markup to original wikicode window.onload= monks2wiki; // on submit of form wikisyntax to PM markup textarea.form.onsubmit = wiki2monks; } // ********** test code ********** /* test heading() */ function t_heading () { var t='= eins\n== zwei\n=== drei'; //console.log(t); var a=heading(t); //console.log(a); var b=heading(a,1); // console.log(b); var a=heading(b); var b=heading(a,1); if (t!=b) { console.log('heading test FAILED: \n'+t+'\n->\n'+a+'\n->\n'+b) +; } else { console.log("heading test OK"); } } /* END OF WIKIFEATURE */
Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!
codelink corrected, including another codearea changed the index to 3
¹) there is a long To-Do list left, but the idea of open source is to attract collaborators and/or forks ... right? ;-)
|
---|