##// END OF EJS Templates
Update LICENSE.md to include license information about Codemirror 3.15...
Update LICENSE.md to include license information about Codemirror 3.15 Add information to the LICENSE.md file to include the information provided in the codemirror-3.15/LICENSE file. Also, note that other license and copyright information also appears in .../public/js/mode/ sub-directories.

File last commit:

r4026:a60a0e90 default
r4121:8c543e37 rhodecode-2.2.5-gpl
Show More
tiddlywiki.js
353 lines | 9.5 KiB | application/javascript | JavascriptLexer
/***
|''Name''|tiddlywiki.js|
|''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
|''Author''|PMario|
|''Version''|0.1.7|
|''Status''|''stable''|
|''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
|''Documentation''|http://codemirror.tiddlyspace.com/|
|''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
|''CoreVersion''|2.5.0|
|''Requires''|codemirror.js|
|''Keywords''|syntax highlighting color code mirror codemirror|
! Info
CoreVersion parameter is needed for TiddlyWiki only!
***/
//{{{
CodeMirror.defineMode("tiddlywiki", function () {
// Tokenizer
var textwords = {};
var keywords = function () {
function kw(type) {
return { type: type, style: "macro"};
}
return {
"allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'),
"newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'),
"permaview": kw('permaview'), "saveChanges": kw('saveChanges'),
"search": kw('search'), "slider": kw('slider'), "tabs": kw('tabs'),
"tag": kw('tag'), "tagging": kw('tagging'), "tags": kw('tags'),
"tiddler": kw('tiddler'), "timeline": kw('timeline'),
"today": kw('today'), "version": kw('version'), "option": kw('option'),
"with": kw('with'),
"filter": kw('filter')
};
}();
var isSpaceName = /[\w_\-]/i,
reHR = /^\-\-\-\-+$/, // <hr>
reWikiCommentStart = /^\/\*\*\*$/, // /***
reWikiCommentStop = /^\*\*\*\/$/, // ***/
reBlockQuote = /^<<<$/,
reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ js block start
reJsCodeStop = /^\/\/\}\}\}$/, // //}}} js stop
reXmlCodeStart = /^<!--\{\{\{-->$/, // xml block start
reXmlCodeStop = /^<!--\}\}\}-->$/, // xml stop
reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start
reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop
reUntilCodeStop = /.*?\}\}\}/;
function chain(stream, state, f) {
state.tokenize = f;
return f(stream, state);
}
// Used as scratch variables to communicate multiple values without
// consing up tons of objects.
var type, content;
function ret(tp, style, cont) {
type = tp;
content = cont;
return style;
}
function jsTokenBase(stream, state) {
var sol = stream.sol(), ch;
state.block = false; // indicates the start of a code block.
ch = stream.peek(); // don't eat, to make matching simpler
// check start of blocks
if (sol && /[<\/\*{}\-]/.test(ch)) {
if (stream.match(reCodeBlockStart)) {
state.block = true;
return chain(stream, state, twTokenCode);
}
if (stream.match(reBlockQuote)) {
return ret('quote', 'quote');
}
if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {
return ret('code', 'comment');
}
if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {
return ret('code', 'comment');
}
if (stream.match(reHR)) {
return ret('hr', 'hr');
}
} // sol
ch = stream.next();
if (sol && /[\/\*!#;:>|]/.test(ch)) {
if (ch == "!") { // tw header
stream.skipToEnd();
return ret("header", "header");
}
if (ch == "*") { // tw list
stream.eatWhile('*');
return ret("list", "comment");
}
if (ch == "#") { // tw numbered list
stream.eatWhile('#');
return ret("list", "comment");
}
if (ch == ";") { // definition list, term
stream.eatWhile(';');
return ret("list", "comment");
}
if (ch == ":") { // definition list, description
stream.eatWhile(':');
return ret("list", "comment");
}
if (ch == ">") { // single line quote
stream.eatWhile(">");
return ret("quote", "quote");
}
if (ch == '|') {
return ret('table', 'header');
}
}
if (ch == '{' && stream.match(/\{\{/)) {
return chain(stream, state, twTokenCode);
}
// rudimentary html:// file:// link matching. TW knows much more ...
if (/[hf]/i.test(ch)) {
if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) {
return ret("link", "link");
}
}
// just a little string indicator, don't want to have the whole string covered
if (ch == '"') {
return ret('string', 'string');
}
if (ch == '~') { // _no_ CamelCase indicator should be bold
return ret('text', 'brace');
}
if (/[\[\]]/.test(ch)) { // check for [[..]]
if (stream.peek() == ch) {
stream.next();
return ret('brace', 'brace');
}
}
if (ch == "@") { // check for space link. TODO fix @@...@@ highlighting
stream.eatWhile(isSpaceName);
return ret("link", "link");
}
if (/\d/.test(ch)) { // numbers
stream.eatWhile(/\d/);
return ret("number", "number");
}
if (ch == "/") { // tw invisible comment
if (stream.eat("%")) {
return chain(stream, state, twTokenComment);
}
else if (stream.eat("/")) { //
return chain(stream, state, twTokenEm);
}
}
if (ch == "_") { // tw underline
if (stream.eat("_")) {
return chain(stream, state, twTokenUnderline);
}
}
// strikethrough and mdash handling
if (ch == "-") {
if (stream.eat("-")) {
// if strikethrough looks ugly, change CSS.
if (stream.peek() != ' ')
return chain(stream, state, twTokenStrike);
// mdash
if (stream.peek() == ' ')
return ret('text', 'brace');
}
}
if (ch == "'") { // tw bold
if (stream.eat("'")) {
return chain(stream, state, twTokenStrong);
}
}
if (ch == "<") { // tw macro
if (stream.eat("<")) {
return chain(stream, state, twTokenMacro);
}
}
else {
return ret(ch);
}
// core macro handling
stream.eatWhile(/[\w\$_]/);
var word = stream.current(),
known = textwords.propertyIsEnumerable(word) && textwords[word];
return known ? ret(known.type, known.style, word) : ret("text", null, word);
} // jsTokenBase()
// tw invisible comment
function twTokenComment(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = jsTokenBase;
break;
}
maybeEnd = (ch == "%");
}
return ret("comment", "comment");
}
// tw strong / bold
function twTokenStrong(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "'" && maybeEnd) {
state.tokenize = jsTokenBase;
break;
}
maybeEnd = (ch == "'");
}
return ret("text", "strong");
}
// tw code
function twTokenCode(stream, state) {
var ch, sb = state.block;
if (sb && stream.current()) {
return ret("code", "comment");
}
if (!sb && stream.match(reUntilCodeStop)) {
state.tokenize = jsTokenBase;
return ret("code", "comment");
}
if (sb && stream.sol() && stream.match(reCodeBlockStop)) {
state.tokenize = jsTokenBase;
return ret("code", "comment");
}
ch = stream.next();
return (sb) ? ret("code", "comment") : ret("code", "comment");
}
// tw em / italic
function twTokenEm(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = jsTokenBase;
break;
}
maybeEnd = (ch == "/");
}
return ret("text", "em");
}
// tw underlined text
function twTokenUnderline(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "_" && maybeEnd) {
state.tokenize = jsTokenBase;
break;
}
maybeEnd = (ch == "_");
}
return ret("text", "underlined");
}
// tw strike through text looks ugly
// change CSS if needed
function twTokenStrike(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "-" && maybeEnd) {
state.tokenize = jsTokenBase;
break;
}
maybeEnd = (ch == "-");
}
return ret("text", "strikethrough");
}
// macro
function twTokenMacro(stream, state) {
var ch, word, known;
if (stream.current() == '<<') {
return ret('brace', 'macro');
}
ch = stream.next();
if (!ch) {
state.tokenize = jsTokenBase;
return ret(ch);
}
if (ch == ">") {
if (stream.peek() == '>') {
stream.next();
state.tokenize = jsTokenBase;
return ret("brace", "macro");
}
}
stream.eatWhile(/[\w\$_]/);
word = stream.current();
known = keywords.propertyIsEnumerable(word) && keywords[word];
if (known) {
return ret(known.type, known.style, word);
}
else {
return ret("macro", null, word);
}
}
// Interface
return {
startState: function () {
return {
tokenize: jsTokenBase,
indented: 0,
level: 0
};
},
token: function (stream, state) {
if (stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
return style;
},
electricChars: ""
};
});
CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");
//}}}