tzk/tzk/editions/tzk/plugins/cmplus/$__plugins_tiddlywiki_codem...

395 lines
13 KiB
JavaScript

// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
/***
|''Name''|tw5.js|
|''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
|''Original Contributor''|PMario|
|''Author''|[[adithya-badidey|https://github.com/adithya-badidey]]|
|''Version''|0.1.8|
|''Status''|''stable''|
|''Source''|[[GitHub|https://github.com/adithya-badidey/TW5-codemirror-plus]]|
|''Documentation''|https://codemirror.tiddlyspace.com/|
|''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
|''Requires''|codemirror.js|
|''Keywords''|syntax highlighting color code mirror codemirror|
!! Tiddlywiki Metadata
Name: $:/plugins/tiddlywiki/codemirror/mode/tw5/tw5.js
Type: application/javascript
Additional Field:
module-type: codemirror
Info: CoreVersion parameter is needed for TiddlyWiki only!
***/
(function (mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function (CodeMirror) {
"use strict";
CodeMirror.defineMode("tiddlywiki5", function () {
// Tokenizer
var textwords = {};
var keywords = {
"changecount": true, "colour": true,
"colour-picker": true, "contrastcolour": true,
"copy-to-clipboard": true, "csvtiddlers": true,
"datauri": true, "dumpvariables": true,
"image-picker": true, "jsontiddler": true,
"jsontiddlers": true, "lingo": true,
"list-links": true, "list-links-draggable": true,
"list-tagged-draggable": true, "list-thumbnails": true,
"makedatauri": true, "now": true,
"qualify": true, "resolvepath": true,
"box-shadow": true, "filter": true,
"transition": true, "background-linear-gradient": true,
"transform-origin": true, "toc": true,
"toc-expandable": true, "toc-selective-expandable": true,
"toc-tabbed-internal-nav": true, "toc-tabbed-external-nav": true,
"tabs": true, "tag": true,
"tag-picker": true, "tag-pill": true,
"thumbnail": true, "timeline": true,
"tree": true, "unusedtitle": true,
"version": true
};
var isSpaceName = /[\w_\-]/i,
reHR = /^\-\-\-\-+$/, // <hr>
reBlockQuote = /^<<</,
rePreStart = /^```$/;
function chain(stream, state, f) {
state.tokenize = f;
return f(stream, state);
}
function tokenBase(stream, state) {
var sol = stream.sol(), // sol() -> Returns true only if the stream is at the start of the line.
ch = stream.peek(); // Returns the next character in the stream without advancing it. Will return a null at the end of the line.
// check start of blocks
if (sol && /[<\/\*{}\-`]/.test(ch)) { //is at the start of a line and the next char is not
if (stream.match(reBlockQuote)) {
return chain(stream, state, twTokenQuote);
}
if (stream.match(reHR))
return 'hr';
if (stream.match(rePreStart))
return chain(stream, state, twTokenPre);
}
stream.next();
if (sol && /[\/\*!#;:>|]/.test(ch)) {
if (ch == "!") { // tw header
var count = 1;
while (stream.eat('!'))
count++;
stream.skipToEnd();
return "h" + count;
}
if (ch == "*" || ch == "#") { // tw list
var count = 1;
while (stream.eat('*') || stream.eat('#'))
count++;
return "list" + count;
}
if (ch == ";") { // definition list, term
stream.eatWhile(';');
return "list1";
}
if (ch == ":") { // definition list, description
stream.eatWhile(':');
return "list2";
}
if (ch == ">") { // single line quote
stream.eatWhile(">");
return "quote";
}
if (ch == '|')
return 'header';
}
// rudimentary html:// file:// link matching. TW knows much more ...
if (/[hf]/i.test(ch) &&
/[ti]/i.test(stream.peek()) &&
stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i, true))
return "externallink";
if (ch == '`') { //
return chain(stream, state, twTokenMonospace);
}
if (ch == "/" && stream.eat("/")) { //
return chain(stream, state, twTokenEm);
}
if (ch == "{" && stream.eat("{"))
return chain(stream, state, twTranslclude);
if (ch == "[" && stream.eat("[")) // tw InternalLink
return chain(stream, state, twInternalLink);
if (ch == "_" && stream.eat("_")) // tw underline
return chain(stream, state, twTokenUnderline);
if (ch == "^" && stream.eat("^"))
return chain(stream, state, twSuperscript);
if (ch == "," && stream.eat(",")) // tw underline
return chain(stream, state, twSubscript);
// tw strikethrough
if (ch == "~" && stream.eat("~")) {
return chain(stream, state, twTokenStrike);
}
if (ch == "'" && stream.eat("'")) // tw bold
return chain(stream, state, twTokenStrong);
if (ch == "<" && stream.eat("<")) // tw macro
return chain(stream, state, twTokenMacro);
return null
}
// // tw invisible comment
// function twTokenComment(stream, state) {
// var maybeEnd = false, ch;
// while (ch = stream.next()) {
// if (ch == "/" && maybeEnd) {
// state.tokenize = tokenBase;
// break;
// }
// maybeEnd = (ch == "%");
// }
// return "comment";
// }
// tw strong / bold
function twTokenStrong(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "'" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "'");
}
return "strong";
}
function twTokenMonospace(stream, state) {
var ch;
while (ch = stream.next()) {
if (ch == "`") {
state.tokenize = tokenBase;
break;
}
}
return "monospace";
}
// tw em / italic
function twTokenEm(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "/");
}
return "em";
}
// tw transclusions
function twTranslclude(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "}" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "}");
}
return "transclude";
}
// tw internal links
function twInternalLink(stream, state) {
if (stream.current() == '[[') {
state.pastDivider = false;
// console.log("Start of link");
return 'link';
}
if (stream.peek() == ']') {
stream.next()
if(stream.next() == ']') {
state.tokenize = tokenBase;
// console.log("End of link");
return 'link';
}
}
var pastDivider = state.pastDivider,
ch;
while (ch = stream.peek()) {
// console.log("Peeking :" + ch);
if (!pastDivider && ch=='|') {
stream.next();
state.pastDivider = true;
// console.log("Past the divider");
return 'link';
}
if (ch == "]" && stream.peek() == "]") {
// console.log("Found end of link");
return "internallink";
}
ch = stream.next();
if (/[hf]/i.test(ch) &&
/[ti]/i.test(stream.peek()) &&
stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i, true)) {
// console.log("Found external link");
return "externallink";
}
stream.eatWhile(/[^|\]]/);
}
return null;
}
// tw underlined text
function twTokenUnderline(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "_" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "_");
}
return "underlined";
}
function twSubscript(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "," && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == ",");
}
return "subscript";
}
function twSuperscript(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "^" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "^");
}
return "superscript";
}
function twTokenStrike(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "~" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "~");
}
return "strikethrough";
}
function twTokenPre(stream, state) {
var sol = stream.sol(), maybeEnd = false, surelyend = false, ch;
while (ch = stream.next()) {
if (ch == '`' && surelyend && stream.eol()) {
stream.next();
state.tokenize = tokenBase;
return "pre";
}
surelyend = (maybeEnd && (ch == '`'));
maybeEnd = (sol && ch == '`');
sol = stream.sol();
}
return "pre";
}
function twTokenQuote(stream, state) {
var sol = stream.sol(), maybeEnd = false, surelyend = false, ch;
while (ch = stream.next()) {
if (ch == '<' && surelyend) {
stream.skipToEnd();
state.tokenize = tokenBase;
return "quote";
}
surelyend = (maybeEnd && (ch == '<'));
maybeEnd = (sol && ch == '<');
sol = stream.sol();
}
return "quote";
}
function twTokenMacro(stream, state) {
if (stream.current() == '<<') {
return 'macro';
}
var ch = stream.next();
if (!ch) {
state.tokenize = tokenBase;
return null;
}
if (ch == ">") {
if (stream.peek() == '>') {
stream.next();
state.tokenize = tokenBase;
return "macro";
}
}
stream.eatWhile(/[\w\$_]/);
return keywords.propertyIsEnumerable(stream.current()) ? "keyword" : "macro"
}
// Interface
return {
startState: function () {
return { tokenize: tokenBase };
},
token: function (stream, state) {
if (stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
return style;
}
};
});
CodeMirror.defineMIME("text/vnd.tiddlywiki", "tiddlywiki5");
});