diff --git a/src/config/langages.js b/src/config/langages.js
new file mode 100644
index 0000000..9fceba8
--- /dev/null
+++ b/src/config/langages.js
@@ -0,0 +1,25 @@
+module.exports = [
+ "python",
+ "c",
+ "c++",
+ "c#",
+ "javascript",
+ "java",
+ "haskell",
+ "smalltalk",
+ "coffescript",
+ "css",
+ "d",
+ "go",
+ "haskell",
+ "html",
+ "json",
+ "lua",
+ "php",
+ "r",
+ "ruby",
+ "scheme",
+ "shell",
+ "sql",
+ 'oz',
+];
diff --git a/src/db/MongoDB.js b/src/db/MongoDB.js
index 806f2ef..88c963e 100644
--- a/src/db/MongoDB.js
+++ b/src/db/MongoDB.js
@@ -1,6 +1,7 @@
const { MongoClient, ObjectID } = require("mongodb");
var crypto = require('crypto');
const { nanoid } = require('nanoid');
+const languages = require('../config/langages');
const configs = require('../config/config');
const utils = require('../utils');
@@ -12,7 +13,6 @@ const baseCode = [
{uuid: utils.uuid(Math.random().toString(), 10), content: ' main(\'Hello World !\')'}
];
-
class MongoDB {
constructor (url) {
this.client = new MongoClient(url, {
@@ -35,7 +35,7 @@ class MongoDB {
}
}
- async createDocument (language) {
+ async createDocument (documentLanguage) {
let doc = {
content: baseCode,
creationDate: Date.now(),
@@ -45,7 +45,7 @@ class MongoDB {
editors: [],
documentLink: '',
linkView: '',
- language: language,
+ language: documentLanguage,
tab: 4
};
try {
@@ -173,7 +173,7 @@ class MongoDB {
}
async changeLanguage(documentLink, newLanguage) {
- if (["python"].includes(newLanguage)) {
+ if (languages.includes(newLanguage)) {
return this.changeParam(documentLink, 'language', newLanguage);
}
}
diff --git a/src/publics/css/base.less b/src/publics/css/base.less
index 098cce3..13f5bfa 100644
--- a/src/publics/css/base.less
+++ b/src/publics/css/base.less
@@ -2,7 +2,7 @@
| Generic |
\*******************/
-@background-color: #222;
+@background-color: #222222;
@color: #fff;
@font: sans-serif;
@absolute-color: #d5e6ed;
diff --git a/src/publics/css/editor.less b/src/publics/css/editor.less
index bcdfdf5..8ab332e 100644
--- a/src/publics/css/editor.less
+++ b/src/publics/css/editor.less
@@ -1,3 +1,7 @@
+@background-color: #222222;
+@color: #fff;
+@header-height: 60px;
+
/******************\
| Header |
\******************/
@@ -57,3 +61,56 @@ section#editor{
background-color: red;
border-radius: 10px;
}
+
+/*******************\
+| Navigation Bar |
+\*******************/
+
+#customise{
+ position: fixed;
+ top: 1.1 * @header-height;
+ right: 0;
+ width: 20%;
+ height: 100%;
+ max-width: 300px;
+ min-width: 200px;
+ padding: 20px;
+ background-color: darken(@background-color, 2%);
+ border-left: 1px solid #111111;
+ z-index: 5;
+
+ ul{
+ list-style: none;
+
+ li{
+ padding-bottom: 20px;
+
+ h3{
+ padding: 5px 0;
+ color: darken(@color, 50%);
+ letter-spacing: 3px;
+ border-bottom: 1px solid lighten(@background-color, 10%);
+ display: inline;
+ }
+
+ > :not(h3){
+ padding: 7px;
+ margin-top: 20px;
+ border-radius: 10px;
+ }
+
+ select,
+ input{
+ color: @color;
+ background-color: lighten(@background-color, 5%);
+ border-color: @background-color;
+ width: 90%;
+ }
+
+ #qrcode{
+ background-color: white;
+ display: inline-block;
+ }
+ }
+ }
+}
diff --git a/src/publics/js/dev/component/custom.js b/src/publics/js/dev/component/custom.js
index cd2af38..15932fb 100644
--- a/src/publics/js/dev/component/custom.js
+++ b/src/publics/js/dev/component/custom.js
@@ -1,3 +1,62 @@
/**
- * Tab customization (allow convert current file)
+ * Tab customization
*/
+
+import {editor, socket} from "/js/dev/page/editor.js";
+import {patterns} from "/js/dev/page/editor/prism/patterns.js";
+import PrismCustom from "/js/dev/page/editor/prism/prismCustom.js";
+
+export default class Customize{
+ /** Init the customize object
+ * @param {Editable} editable
+ */
+ constructor(editable) {
+ this.editable = editable;
+
+ document.getElementById('option-language').addEventListener('change', e => {
+ language = e.target.value.toLowerCase();
+ this.editable.updateAllHighlighting();
+ socket.send('language', {language});
+ });
+
+ document.addEventListener('socket.receive.language', e => {
+ if(Object.keys(patterns).includes(e.detail.language.toLowerCase())){
+ language = e.detail.language.toLowerCase();
+ document.getElementById('option-language').value = language;
+ this.editable.updateAllHighlighting();
+ }
+ });
+
+ for(const lang of Object.keys(patterns)){
+ const option = document.createElement('option');
+ option.innerText = lang;
+ if(lang === language) option.selected = true;
+ document.getElementById('option-language').appendChild(option);
+ }
+
+ document.getElementById('option-space-size').addEventListener('change', e => {
+ editor.tab.setSize(e.target.value);
+
+ for(const child of this.editable.editable.children){
+ child.innerText = editor.tab.updateText(child.innerText);
+ new PrismCustom(child, language).apply();
+ }
+
+ socket.send('changeTabSize', {size: e.target.value});
+ });
+
+ document.getElementById('option-space-size').value = this.editable.tab.size;
+
+ document.addEventListener('socket.receive.changeTabSize', e => {
+ if(e.detail.size && Number.isInteger(parseInt(e.detail.size))){
+ editor.tab.setSize(e.detail.size);
+ document.getElementById('option-space-size').value = e.detail.size;
+
+ for(const child of this.editable.editable.children){
+ child.innerText = editor.tab.updateText(child.innerText);
+ new PrismCustom(child, language).apply();
+ }
+ }
+ });
+ }
+}
diff --git a/src/publics/js/dev/lib/qrcode.min.js b/src/publics/js/dev/lib/qrcode.min.js
new file mode 100644
index 0000000..1911078
--- /dev/null
+++ b/src/publics/js/dev/lib/qrcode.min.js
@@ -0,0 +1,11 @@
+/**
+ * @fileoverview
+ * - Using the 'QRCode for Javascript library'
+ * - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
+ * - this library has no dependencies.
+ *
+ * @author davidshimjs
+ * @see http://www.d-project.com/
+ * @see http://jeromeetienne.github.com/jquery-qrcode/
+ */
+var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j=0?p.get(q):0}}for(var r=0,m=0;mm;m++)for(var j=0;jm;m++)for(var j=0;j=0;)b^=f.G15<=0;)b^=f.G18<>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;cf;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=[''],h=0;d>h;h++){g.push("");for(var i=0;d>i;i++)g.push(' | ');g.push("
")}g.push("
"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}();
diff --git a/src/publics/js/dev/page/editor.js b/src/publics/js/dev/page/editor.js
index 174bebd..29d91bf 100644
--- a/src/publics/js/dev/page/editor.js
+++ b/src/publics/js/dev/page/editor.js
@@ -5,9 +5,11 @@
* @date Last modification on 16/11/2020
* @version 1.0.1
*/
+import Customize from "/js/dev/component/custom.js";
import Cursor from "/js/dev/page/editor/cursor.js";
import download from "/js/dev/page/editor/download.js";
import Editable from "/js/dev/page/editor/editable.js";
+import {patterns} from "/js/dev/page/editor/prism/patterns.js";
import PrismCustom from "/js/dev/page/editor/prism/prismCustom.js";
import EditorSocket from "/js/dev/page/editor/socket.js";
import _ from "/js/dev/utils/element.js";
@@ -16,8 +18,12 @@ export const socket = new EditorSocket(doc_id);
export const editor = new Editable(_.id('editor'));
export const cursor = new Cursor(_.id('editor'));
+download(_.id('download'), _.id('editor'));
+
+if(!Object.keys(patterns).includes(language)) language = 'generic';
+
for(const child of _.id('editor').children){
- new PrismCustom(child, 'python').ApplyWithCaret();
+ new PrismCustom(child, language).apply();
}
-download(_.id('download'), _.id('editor'));
+export const customize = new Customize(editor);
diff --git a/src/publics/js/dev/page/editor/editable.js b/src/publics/js/dev/page/editor/editable.js
index 36778ea..fa6e294 100644
--- a/src/publics/js/dev/page/editor/editable.js
+++ b/src/publics/js/dev/page/editor/editable.js
@@ -19,9 +19,9 @@ import Random from "/js/dev/utils/random.js";
import {insertInText} from "/js/dev/utils/string.js";
export default class Editable{
- constructor(element) {
+ constructor(element, tabSize=initial_size) {
this.editable = element;
- this.tab = new Tab(element, TabType.SPACES, 4);
+ this.tab = Number.isInteger(tabSize) ? new Tab(element, TabType.SPACES, tabSize) : 4;
this.linesManager = new LinesManager(element);
this.last_request = {};
@@ -79,7 +79,7 @@ export default class Editable{
}
break;
default:
- if(!e.ctrlKey && !e.altKey) PrismCustom.onCurrent('python').ApplyWithCaret();
+ if(!e.ctrlKey && !e.altKey) PrismCustom.onCurrent(language).ApplyWithCaret();
}
this.linesManager.change = true;
});
@@ -223,7 +223,7 @@ export default class Editable{
)
);
document.getSelection().collapseToEnd();
- PrismCustom.onCurrent('python').ApplyWithCaret();
+ PrismCustom.onCurrent(language).ApplyWithCaret();
}
/**
@@ -234,7 +234,7 @@ export default class Editable{
const currentElement = getNodeFromAttribute('uuid');
currentElement.innerHTML = insertInText(currentElement.innerText, lines[0], Caret.getBeginPosition(currentElement));
- PrismCustom.onCurrent('python').apply();
+ PrismCustom.onCurrent(language).apply();
let currentUuid = currentElement.getAttribute('uuid');
for(let i=1;i
', '
');
line.remove();
Caret.setPosition(previousSibling, len);
}
@@ -302,4 +302,16 @@ export default class Editable{
}
return requests;
}
+
+ /**
+ * Update all syntax highlighting
+ */
+ updateAllHighlighting(){
+ const current = getNodeFromAttribute('uuid')
+ for(const child of this.editable.children){
+ if(current === child) new PrismCustom(child, language).ApplyWithCaret();
+ else new PrismCustom(child, language).apply();
+
+ }
+ }
}
diff --git a/src/publics/js/dev/page/editor/linesManager.js b/src/publics/js/dev/page/editor/linesManager.js
index 62b7045..fd36446 100644
--- a/src/publics/js/dev/page/editor/linesManager.js
+++ b/src/publics/js/dev/page/editor/linesManager.js
@@ -67,7 +67,7 @@ export default class LinesManager{
let element = this.select(uuid);
if(element){
element.innerText = htmlEncode(content);
- new PrismCustom(element, 'python').apply();
+ new PrismCustom(element, language).apply();
}else{
Debug.warn(`Error when trying to update element with uuid '${uuid}': No div has this uuid.`)
}
diff --git a/src/publics/js/dev/page/editor/prism/patterns.js b/src/publics/js/dev/page/editor/prism/patterns.js
index 85018bc..6b60f3c 100644
--- a/src/publics/js/dev/page/editor/prism/patterns.js
+++ b/src/publics/js/dev/page/editor/prism/patterns.js
@@ -1,3 +1,7 @@
+// Those regex are based on https://github.com/ccampbell/rainbow/tree/master/src/language made by Craig Campbell
+// Big love to them <3
+// For oz it's base on vscode extension : https://github.com/mozart/vscode-oz/blob/master/syntaxes/oz.tmLanguage.json
+
export const patterns = {
generic: [
{
@@ -135,5 +139,1651 @@ export const patterns = {
name: 'comment.docstring',
pattern: /('{3}|"{3})[\s\S]*?\1/gm
}
- ]
-};
\ No newline at end of file
+ ],
+ javascript: [
+
+ /**
+ * matches $. or $(
+ */
+ {
+ name: 'selector',
+ pattern: /\$(?=\.|\()/g
+ },
+ {
+ name: 'support',
+ pattern: /\b(window|document)\b/g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(export|default|from)\b/g
+ },
+ {
+ name: 'function.call',
+ pattern: /\b(then)(?=\()/g
+ },
+ {
+ name: 'variable.language.this',
+ pattern: /\bthis\b/g
+ },
+ {
+ name: 'variable.language.super',
+ pattern: /super(?=\.|\()/g
+ },
+ {
+ name: 'storage.type',
+ pattern: /\b(const|let|var)(?=\s)/g
+ },
+ {
+ matches: {
+ 1: 'support.property'
+ },
+ pattern: /\.(length|node(Name|Value))\b/g
+ },
+ {
+ matches: {
+ 1: 'support.function'
+ },
+ pattern: /(setTimeout|setInterval)(?=\()/g
+ },
+ {
+ matches: {
+ 1: 'support.method'
+ },
+ pattern: /\.(getAttribute|replace|push|getElementById|getElementsByClassName|setTimeout|setInterval)(?=\()/g
+ },
+
+ /**
+ * matches any escaped characters inside of a js regex pattern
+ *
+ * @see https://github.com/ccampbell/rainbow/issues/22
+ *
+ * this was causing single line comments to fail so it now makes sure
+ * the opening / is not directly followed by a *
+ *
+ * The body of the regex to match a regex was borrowed from:
+ * http://stackoverflow.com/a/17843773/421333
+ */
+ {
+ name: 'string.regexp',
+ matches: {
+ 1: 'string.regexp.open',
+ 2: {
+ name: 'constant.regexp.escape',
+ pattern: /\\(.){1}/g
+ },
+ 3: 'string.regexp.close',
+ 4: 'string.regexp.modifier'
+ },
+ pattern: /(\/)((?![*+?])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+)(\/)(?!\/)([igm]{0,3})/g
+ },
+
+ /**
+ * matches runtime function declarations
+ */
+ {
+ matches: {
+ 1: 'storage.type',
+ 3: 'entity.function'
+ },
+ pattern: /(var)?(\s|^)(\S+)(?=\s?=\s?function\()/g
+ },
+
+ /**
+ * matches constructor call
+ */
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'variable.type'
+ },
+ pattern: /(new)\s+(?!Promise)([^\(]*)(?=\()/g
+ },
+
+ /**
+ * matches any function call in the style functionName: function()
+ */
+ {
+ name: 'entity.function',
+ pattern: /(\w+)(?=:\s{0,}function)/g
+ },
+ {
+ name: 'constant.other',
+ pattern: /\*(?= as)/g
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'constant.other'
+ },
+ pattern: /(export)\s+(\*)/g
+ },
+ {
+ matches: {
+ 1: 'storage.type.accessor',
+ 2: 'entity.name.function'
+ },
+ pattern: /(get|set)\s+(\w+)(?=\()/g
+ },
+ {
+ matches: {
+ 2: 'entity.name.function'
+ },
+ pattern: /(^\s*)(\w+)(?=\([^\)]*?\)\s*\{)/gm
+ },
+ {
+ matches: {
+ 1: 'storage.type.class',
+ 2: 'entity.name.class',
+ 3: 'storage.modifier.extends',
+ 4: 'entity.other.inherited-class'
+ },
+ pattern: /(class)\s+(\w+)(?:\s+(extends)\s+(\w+))?(?=\s*\{)/g
+ },
+ {
+ name: 'storage.type.function.arrow',
+ pattern: /=>/g
+ },
+ {
+ name: 'support.class.promise',
+ pattern: /\bPromise(?=(\(|\.))/g
+ }
+ ],
+ java: [
+ {
+ name: "constant",
+ pattern: /\b(false|null|true|[A-Z_]+)\b/g
+ },
+ {
+ matches: {
+ 1: "keyword",
+ 2: "support.namespace"
+ },
+ pattern: /(import|package)\s(.+)/g
+ },
+ {
+ // see http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
+ name: "keyword",
+ pattern: /\b(abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while)\b/g
+ },
+ {
+ name: "string",
+ pattern: /(".*?")/g
+ },
+ {
+ name: "char",
+ pattern: /(')(.|\\.|\\u[\dA-Fa-f]{4})\1/g
+ },
+ {
+ name: "integer",
+ pattern: /\b(0x[\da-f]+|\d+)L?\b/g
+ },
+ {
+ name: "comment",
+ pattern: /\/\*[\s\S]*?\*\/|(\/\/).*?$/gm
+ },
+ {
+ name: "support.annotation",
+ pattern: /@\w+/g
+ },
+ {
+ matches: {
+ 1: "entity.function"
+ },
+ pattern: /([^@\.\s]+)\(/g
+ },
+ {
+ name: "entity.class",
+ pattern: /\b([A-Z]\w*)\b/g
+ },
+ {
+ // see http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
+ name: "operator",
+ pattern: /(\+{1,2}|-{1,2}|~|!|\*|\/|%|(?:<){1,2}|(?:>){1,3}|instanceof|(?:&){1,2}|\^|\|{1,2}|\?|:|(?:=|!|\+|-|\*|\/|%|\^|\||(?:<){1,2}|(?:>){1,3})?=)/g
+ }
+ ],
+ c: [
+ {
+ name: 'meta.preprocessor',
+ matches: {
+ 1: [
+ {
+ matches: {
+ 1: 'keyword.define',
+ 2: 'entity.name'
+ },
+ pattern: /(\w+)\s(\w+)\b/g
+ },
+ {
+ name: 'keyword.define',
+ pattern: /endif/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\d+/g
+ },
+ {
+ matches: {
+ 1: 'keyword.include',
+ 2: 'string'
+ },
+ pattern: /(include)\s(.*?)$/g
+ }
+ ]
+ },
+ pattern: /\#([\S\s]*?)$/gm
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(do|goto|typedef)\b/g
+ },
+ {
+ name: 'entity.label',
+ pattern: /\w+:/g
+ },
+ {
+ matches: {
+ 1: 'storage.type',
+ 3: 'storage.type',
+ 4: 'entity.name.function'
+ },
+ pattern: /\b((un)?signed|const)? ?(void|char|short|int|long|float|double)\*? +((\w+)(?= ?\())?/g
+ },
+ {
+ matches: {
+ 2: 'entity.name.function'
+ },
+ pattern: /(\w|\*) +((\w+)(?= ?\())/g
+ },
+ {
+ name: 'storage.modifier',
+ pattern: /\b(static|extern|auto|register|volatile|inline)\b/g
+ },
+ {
+ name: 'support.type',
+ pattern: /\b(struct|union|enum)\b/g
+ }
+ ],
+ coffescript: [
+ {
+ name: 'comment.block',
+ pattern: /(\#{3})[\s\S]*\1/gm
+ },
+ {
+ name: 'string.block',
+ pattern: /('{3}|"{3})[\s\S]*\1/gm
+ },
+
+ /**
+ * multiline regex with comments
+ */
+ {
+ name: 'string.regex',
+ matches: {
+ 2: {
+ name: 'comment',
+ pattern: /\#(.*?)(?=\n)/g
+ }
+ },
+ pattern: /(\/{3})([\s\S]*)\1/gm
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\b(in|when|is|isnt|of|not|unless|until|super)(?=\b)/gi
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\?/g
+ },
+ {
+ name: 'constant.language',
+ pattern: /\b(undefined|yes|on|no|off)\b/g
+ },
+ {
+ name: 'keyword.variable.coffee',
+ pattern: /@(\w+)/gi
+ },
+
+ /**
+ * reset global keywards from generic
+ */
+ {
+ name: 'reset',
+ pattern: /object|class|print/gi
+ },
+
+ /**
+ * named function
+ */
+ {
+ 'matches' : {
+ 1: 'entity.name.function',
+ 2: 'keyword.operator',
+ 3: {
+ name: 'function.argument.coffee',
+ pattern: /([\@\w]+)/g
+ },
+ 4: 'keyword.function'
+ },
+ pattern: /(\w+)\s{0,}(=|:)\s{0,}\((.*?)((-|=)>)/gi
+ },
+
+ /**
+ * anonymous function
+ */
+ {
+ matches: {
+ 1: {
+ name: 'function.argument.coffee',
+ pattern: /([\@\w]+)/g
+ },
+ 2: 'keyword.function'
+ },
+ pattern: /\s\((.*?)\)\s{0,}((-|=)>)/gi
+ },
+
+ /**
+ * direct function no arguments
+ */
+ {
+ 'matches' : {
+ 1: 'entity.name.function',
+ 2: 'keyword.operator',
+ 3: 'keyword.function'
+ },
+ pattern: /(\w+)\s{0,}(=|:)\s{0,}((-|=)>)/gi
+ },
+
+ /**
+ * class definitions
+ */
+ {
+ matches: {
+ 1: 'storage.class',
+ 2: 'entity.name.class',
+ 3: 'storage.modifier.extends',
+ 4: 'entity.other.inherited-class'
+ },
+ pattern: /\b(class)\s(\w+)(\sextends\s)?([\w\\]*)?\b/g
+ },
+
+ /**
+ * object instantiation
+ */
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(new)\s(.*?)(?=\s)/g
+ }
+ ],
+ 'c#': [
+ {
+ // @see http://msdn.microsoft.com/en-us/library/23954zh5.aspx
+ name: 'constant',
+ pattern: /\b(false|null|true)\b/g
+ },
+ {
+ // @see http://msdn.microsoft.com/en-us/library/x53a06bb%28v=vs.100%29.aspx
+ // Does not support putting an @ in front of a keyword which makes it not a keyword anymore.
+ name: 'keyword',
+ pattern: /\b(abstract|add|alias|ascending|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|double|do|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|foreach|for|from|get|global|goto|group|if|implicit|int|interface|internal|into|in|is|join|let|lock|long|namespace|new|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|try|typeof|uint|unchecked|ulong|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/g
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /(typeof)\s([^\$].*?)(\)|;)/g
+ },
+ {
+ matches: {
+ 1: 'keyword.namespace',
+ 2: {
+ name: 'support.namespace',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(namespace)\s(.*?);/g
+ },
+ {
+ matches: {
+ 1: 'storage.modifier',
+ 2: 'storage.class',
+ 3: 'entity.name.class',
+ 4: 'storage.modifier.extends',
+ 5: 'entity.other.inherited-class'
+ },
+ pattern: /\b(abstract|sealed)?\s?(class)\s(\w+)(\sextends\s)?([\w\\]*)?\s?\{?(\n|\})/g
+ },
+ {
+ name: 'keyword.static',
+ pattern: /\b(static)\b/g
+ },
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+
+ },
+ pattern: /\b(new)\s([^\$].*?)(?=\)|\(|;|&)/g
+ },
+ {
+ name: 'string',
+ pattern: /(")(.*?)\1/g
+ },
+ {
+ name: 'integer',
+ pattern: /\b(0x[\da-f]+|\d+)\b/g
+ },
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\/|(\/\/)[\s\S]*?$/gm
+ },
+ {
+ name: 'operator',
+ // @see http://msdn.microsoft.com/en-us/library/6a71f45d%28v=vs.100%29.aspx
+ // ++ += + -- -= - <<= << <= => >>= >> >= != ! ~ ^ || && &= & ?? :: : *= * |= %= |= == =
+ pattern: /(\+\+|\+=|\+|--|-=|-|<<=|<<|<=|=>|>>=|>>|>=|!=|!|~|\^|\|\||&&|&=|&|\?\?|::|:|\*=|\*|\/=|%=|\|=|==|=)/g
+ },
+ {
+ // @see http://msdn.microsoft.com/en-us/library/ed8yd1ha%28v=vs.100%29.aspx
+ name: 'preprocessor',
+ pattern: /(\#if|\#else|\#elif|\#endif|\#define|\#undef|\#warning|\#error|\#line|\#region|\#endregion|\#pragma)[\s\S]*?$/gm
+ }
+ ],
+ css: [
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\//gm
+ },
+ {
+ name: 'constant.hex-color',
+ pattern: /#([a-f0-9]{3}|[a-f0-9]{6})(?=;|\s|,|\))/gi
+ },
+ {
+ matches: {
+ 1: 'constant.numeric',
+ 2: 'keyword.unit'
+ },
+ pattern: /(\d+)(px|em|cm|s|%)?/g
+ },
+ {
+ name: 'string',
+ pattern: /('|")(.*?)\1/g
+ },
+ {
+ name: 'support.css-property',
+ matches: {
+ 1: 'support.vendor-prefix'
+ },
+ pattern: /(-o-|-moz-|-webkit-|-ms-)?[\w-]+(?=\s?:)(?!.*\{)/g
+ },
+ {
+ matches: {
+ 1: [
+ {
+ name: 'entity.name.sass',
+ pattern: /&/g
+ },
+ {
+ name: 'direct-descendant',
+ pattern: />/g
+ },
+ {
+ name: 'entity.name.class',
+ pattern: /\.[\w\-_]+/g
+ },
+ {
+ name: 'entity.name.id',
+ pattern: /\#[\w\-_]+/g
+ },
+ {
+ name: 'entity.name.pseudo',
+ pattern: /:[\w\-_]+/g
+ },
+ {
+ name: 'entity.name.tag',
+ pattern: /\w+/g
+ }
+ ]
+ },
+ pattern: /([\w\ ,\n:\.\#\&\;\-_]+)(?=.*\{)/g
+ },
+ {
+ matches: {
+ 2: 'support.vendor-prefix',
+ 3: 'support.css-value'
+ },
+ pattern: /(:|,)\s*(-o-|-moz-|-webkit-|-ms-)?([a-zA-Z-]*)(?=\b)(?!.*\{)/g
+ }
+ ],
+ go: [
+ {
+ matches: {
+ 1: [
+ {
+ name: 'keyword.operator',
+ pattern: /\=|\+/g
+ }
+ ],
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\(`|"){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=|:|\+|\{|,)((`|")([^\\\1]|\\.)*?(\3))/gm
+ },
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\/|(\/\/)(?!.*(`|").*?\1).*?$/gm
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\b(d(efault|efer)|fallthrough|go(to)?|range|select)(?=\b)/gi
+ },
+ {
+ name: 'keyword',
+ pattern: /\bpackage(?=\s*\w)/gi
+ },
+ {
+ matches: {
+ 1: 'storage.type',
+ 2: 'entity.name.struct'
+ },
+ pattern: /\b(type)\s+(\w+)\b(?=\s+struct\b)/gi
+ },
+ {
+ matches: {
+ 1: 'storage.type',
+ 2: 'entity.name.type'
+ },
+ pattern: /\b(type)\s+(\w+)\b/gi
+ },
+ {
+ name: 'storage.type',
+ pattern: /\b(bool|byte|complex(64|128)|float(32|64)|func|interface|map|rune|string|struct|u?int(8|16|32|64)?|var)(?=\b)/g
+ },
+ {
+ name: 'keyword.operator.initialize',
+ pattern: /\:=/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(func)\s+(?:\(.*?\))\s+(.*?)(?=\()/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(func)\s+(.*?)(?=\()/g
+ }
+ ],
+ html : [
+ {
+ name: 'source.php.embedded',
+ matches: {
+ 1: 'variable.language.php-tag',
+ 2: {
+ language: 'php'
+ },
+ 3: 'variable.language.php-tag'
+ },
+ pattern: /(<\?php|<\?=?(?!xml))([\s\S]*?)(\?>)/gm
+ },
+ {
+ name: 'source.css.embedded',
+ matches: {
+ 1: {
+ matches: {
+ 1: 'support.tag.style',
+ 2: [
+ {
+ name: 'entity.tag.style',
+ pattern: /^style/g
+ },
+ {
+ name: 'string',
+ pattern: /('|")(.*?)(\1)/g
+ },
+ {
+ name: 'entity.tag.style.attribute',
+ pattern: /(\w+)/g
+ }
+ ],
+ 3: 'support.tag.style'
+ },
+ pattern: /(<\/?)(style.*?)(>)/g
+ },
+ 2: {
+ language: 'css'
+ },
+ 3: 'support.tag.style',
+ 4: 'entity.tag.style',
+ 5: 'support.tag.style'
+ },
+ pattern: /(<style.*?>)([\s\S]*?)(<\/)(style)(>)/gm
+ },
+ {
+ name: 'source.js.embedded',
+ matches: {
+ 1: {
+ matches: {
+ 1: 'support.tag.script',
+ 2: [
+ {
+ name: 'entity.tag.script',
+ pattern: /^script/g
+ },
+
+ {
+ name: 'string',
+ pattern: /('|")(.*?)(\1)/g
+ },
+ {
+ name: 'entity.tag.script.attribute',
+ pattern: /(\w+)/g
+ }
+ ],
+ 3: 'support.tag.script'
+ },
+ pattern: /(<\/?)(script.*?)(>)/g
+ },
+ 2: {
+ language: 'javascript'
+ },
+ 3: 'support.tag.script',
+ 4: 'entity.tag.script',
+ 5: 'support.tag.script'
+ },
+ pattern: /(<script(?! src).*?>)([\s\S]*?)(<\/)(script)(>)/gm
+ },
+ {
+ name: 'comment.html',
+ pattern: /<\!--[\S\s]*?-->/g
+ },
+ {
+ matches: {
+ 1: 'support.tag.open',
+ 2: 'support.tag.close'
+ },
+ pattern: /(<)|(\/?\??>)/g
+ },
+ {
+ name: 'support.tag',
+ matches: {
+ 1: 'support.tag',
+ 2: 'support.tag.special',
+ 3: 'support.tag-name'
+ },
+ pattern: /(<\??)(\/|\!?)(\w+)/g
+ },
+ {
+ matches: {
+ 1: 'support.attribute'
+ },
+ pattern: /([a-z-]+)(?=\=)/gi
+ },
+ {
+ matches: {
+ 1: 'support.operator',
+ 2: 'string.quote',
+ 3: 'string.value',
+ 4: 'string.quote'
+ },
+ pattern: /(=)('|")(.*?)(\2)/g
+ },
+ {
+ matches: {
+ 1: 'support.operator',
+ 2: 'support.value'
+ },
+ pattern: /(=)([a-zA-Z\-0-9]*)\b/g
+ },
+ {
+ matches: {
+ 1: 'support.attribute'
+ },
+ pattern: /\s([\w-]+)(?=\s|>)(?![\s\S]*<)/g
+ }
+ ],
+ json : [
+ {
+ matches: {
+ 0: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"){1}/g
+ }
+ }
+ },
+ pattern: /(\"|\')(\\?.)*?\1/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(-?(0x)?\d*\.?[\da-f]+|NaN|-?Infinity)\b/gi
+ },
+ {
+ name: 'constant.language',
+ pattern: /\b(true|false|null)\b/g
+ }
+ ],
+ lua: [
+ {
+ matches: {
+ 1: {
+ name: 'keyword.operator',
+ pattern: /\=/g
+ },
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=)(('|")([^\\\1]|\\.)*?(\3))/gm
+ },
+ {
+ name: 'comment',
+ pattern: /\-{2}\[{2}\-{2}[\s\S]*?\-{2}\]{2}\-{2}|(\-{2})[\s\S]*?$/gm
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\b((a|e)nd|in|repeat|break|local|return|do|for|then|else(if)?|function|not|if|or|until|while)(?=\b)/gi
+ },
+ {
+ name: 'constant.language',
+ pattern: /true|false|nil/g
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\+|\!|\-|&(gt|lt|amp);|\||\*|\=|#|\.{2}/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(function)\s+(\w+[\:|\.]?\w+?)(?=\()/g
+ },
+ {
+ matches: {
+ 1: 'support.function'
+ },
+ pattern: /\b(print|require|module|\w+\.\w+)(?=\()/g
+ }
+ ],
+ php: [
+ {
+ name: 'support',
+ pattern: /\becho\b/ig
+ },
+ {
+ matches: {
+ 1: 'variable.dollar-sign',
+ 2: 'variable'
+ },
+ pattern: /(\$)(\w+)\b/g
+ },
+ {
+ name: 'constant.language',
+ pattern: /true|false|null/ig
+ },
+ {
+ name: 'constant',
+ pattern: /\b[A-Z0-9_]{2,}\b/g
+ },
+ {
+ name: 'keyword.dot',
+ pattern: /\./g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(die|end(for(each)?|switch|if)|case|require(_once)?|include(_once)?)(?=\b)/ig
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /(instanceof)\s([^\$].*?)(\)|;)/ig
+ },
+
+ /**
+ * these are the top 50 most used PHP functions
+ * found from running a script and checking the frequency of each function
+ * over a bunch of popular PHP frameworks then combining the results
+ */
+ {
+ matches: {
+ 1: 'support.function'
+ },
+ pattern: /\b(array(_key_exists|_merge|_keys|_shift)?|isset|count|empty|unset|printf|is_(array|string|numeric|object)|sprintf|each|date|time|substr|pos|str(len|pos|tolower|_replace|totime)?|ord|trim|in_array|implode|end|preg_match|explode|fmod|define|link|list|get_class|serialize|file|sort|mail|dir|idate|log|intval|header|chr|function_exists|dirname|preg_replace|file_exists)(?=\()/ig
+ },
+ {
+ name: 'variable.language.php-tag',
+ pattern: /(<\?(php)?|\?>)/ig
+ },
+ {
+ matches: {
+ 1: 'keyword.namespace',
+ 2: {
+ name: 'support.namespace',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(namespace|use)\s(.*?);/ig
+ },
+ {
+ matches: {
+ 1: 'storage.modifier',
+ 2: 'storage.class',
+ 3: 'entity.name.class',
+ 4: 'storage.modifier.extends',
+ 5: 'entity.other.inherited-class',
+ 6: 'storage.modifier.extends',
+ 7: 'entity.other.inherited-class'
+ },
+ pattern: /\b(abstract|final)?\s?(class|interface|trait)\s(\w+)(\sextends\s)?([\w\\]*)?(\simplements\s)?([\w\\]*)?\s?\{?(\n|\})/ig
+ },
+ {
+ name: 'keyword.static',
+ pattern: /self::|static::/ig
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function.magic'
+ },
+ pattern: /(function)\s(__.*?)(?=\()/ig
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(function)\s(.*?)(?=\()/ig
+ },
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(new)\s([^\$][a-z0-9_\\]*?)(?=\)|\(|;)/ig
+ },
+ {
+ matches: {
+ 1: {
+ name: 'support.class',
+ pattern: /\w+/g
+ },
+ 2: 'keyword.static'
+ },
+ pattern: /([\w\\]*?)(::)(?=\b|\$)/g
+ },
+ {
+ matches: {
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /(\(|,\s?)([\w\\]*?)(?=\s\$)/g
+ }
+ ],
+ ruby: [
+ /**
+ * __END__ DATA
+ */
+ {
+ matches: {
+ 1: 'variable.language',
+ 2: {
+ language: null
+ }
+ },
+ //find __END__ and consume remaining text
+ pattern: /^(__END__)\n((?:.*\n)*)/gm
+ },
+ /**
+ * Strings
+ * 1. No support for multi-line strings
+ */
+ {
+ name: 'string',
+ matches: {
+ 1: 'string.open',
+ 2: [{
+ name: 'string.interpolation',
+ matches: {
+ 1: 'string.open',
+ 2: {
+ language: 'ruby'
+ },
+ 3: 'string.close'
+ },
+ pattern: /(\#\{)(.*?)(\})/g
+ }],
+ 3: 'string.close'
+ },
+ pattern: /("|`)(.*?[^\\\1])?(\1)/g
+ },
+ {
+ name: 'string',
+ pattern: /('|"|`)([^\\\1\n]|\\.)*?\1/g
+ },
+ {
+ name: 'string',
+ pattern: /%[qQ](?=(\(|\[|\{|<|.)(.*?)(?:'|\)|\]|\}|>|\1))(?:\(\2\)|\[\2\]|\{\2\}|\<\2>|\1\2\1)/g
+ },
+ /**
+ * Heredocs
+ * Heredocs of the form `<<'HTML' ... HTML` are unsupported.
+ */
+ {
+ matches: {
+ 1: 'string',
+ 2: 'string',
+ 3: 'string'
+ },
+ pattern: /(<<)(\w+).*?$([\s\S]*?^\2)/gm
+ },
+ {
+ matches: {
+ 1: 'string',
+ 2: 'string',
+ 3: 'string'
+ },
+ pattern: /(<<\-)(\w+).*?$([\s\S]*?\2)/gm
+ },
+ /**
+ * Regular expressions
+ * Escaped delimiter (`/\//`) is unsupported.
+ */
+ {
+ name: 'string.regexp',
+ matches: {
+ 1: 'string.regexp',
+ 2: {
+ name: 'string.regexp',
+ pattern: /\\(.){1}/g
+ },
+ 3: 'string.regexp',
+ 4: 'string.regexp'
+ },
+ pattern: /(\/)(.*?)(\/)([a-z]*)/g
+ },
+ {
+ name: 'string.regexp',
+ matches: {
+ 1: 'string.regexp',
+ 2: {
+ name: 'string.regexp',
+ pattern: /\\(.){1}/g
+ },
+ 3: 'string.regexp',
+ 4: 'string.regexp'
+ },
+ pattern: /%r(?=(\(|\[|\{|<|.)(.*?)('|\)|\]|\}|>|\1))(?:\(\2\)|\[\2\]|\{\2\}|\<\2>|\1\2\1)([a-z]*)/g
+ },
+ /**
+ * Comments
+ */
+ {
+ name: 'comment',
+ pattern: /#.*$/gm
+ },
+ {
+ name: 'comment',
+ pattern: /^\=begin[\s\S]*?\=end$/gm
+ },
+ /**
+ * Symbols
+ */
+ {
+ matches: {
+ 1: 'constant'
+ },
+ pattern: /(\w+:)[^:]/g
+ },
+ {
+ matches: {
+ 1: 'constant.symbol'
+ },
+ pattern: /[^:](:(?:\w+|(?=['"](.*?)['"])(?:"\2"|'\2')))/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(0x[\da-f]+|[\d_]+)\b/g
+ },
+ {
+ name: 'support.class',
+ pattern: /\b[A-Z]\w*(?=((\.|::)[A-Za-z]|\[))/g
+ },
+ {
+ name: 'constant',
+ pattern: /\b[A-Z]\w*\b/g
+ },
+ /**
+ * Keywords, variables, constants, and operators
+ * In Ruby some keywords are valid method names, e.g., MyClass#yield
+ * Don't mark those instances as "keywords"
+ */
+ {
+ matches: {
+ 1: 'storage.class',
+ 2: 'entity.name.class',
+ 3: 'entity.other.inherited-class'
+ },
+ pattern: /\s*(class)\s+((?:(?:::)?[A-Z]\w*)+)(?:\s+<\s+((?:(?:::)?[A-Z]\w*)+))?/g
+ },
+ {
+ matches: {
+ 1: 'storage.module',
+ 2: 'entity.name.class'
+ },
+ pattern: /\s*(module)\s+((?:(?:::)?[A-Z]\w*)+)/g
+ },
+ {
+ name: 'variable.global',
+ pattern: /\$([a-zA-Z_]\w*)\b/g
+ },
+ {
+ name: 'variable.class',
+ pattern: /@@([a-zA-Z_]\w*)\b/g
+ },
+ {
+ name: 'variable.instance',
+ pattern: /@([a-zA-Z_]\w*)\b/g
+ },
+ {
+ matches: {
+ 1: 'keyword.control'
+ },
+ pattern: /[^\.]\b(BEGIN|begin|case|class|do|else|elsif|END|end|ensure|for|if|in|module|rescue|then|unless|until|when|while)\b(?![?!])/g
+ },
+ {
+ matches: {
+ 1: 'keyword.control.pseudo-method'
+ },
+ pattern: /[^\.]\b(alias|alias_method|break|next|redo|retry|return|super|undef|yield)\b(?![?!])|\bdefined\?|\bblock_given\?/g
+ },
+ {
+ matches: {
+ 1: 'constant.language'
+ },
+ pattern: /\b(nil|true|false)\b(?![?!])/g
+ },
+ {
+ matches: {
+ 1: 'variable.language'
+ },
+ pattern: /\b(__(FILE|LINE)__|self)\b(?![?!])/g
+ },
+ {
+ matches: {
+ 1: 'keyword.special-method'
+ },
+ pattern: /\b(require|gem|initialize|new|loop|include|extend|raise|attr_reader|attr_writer|attr_accessor|attr|catch|throw|private|module_function|public|protected)\b(?![?!])/g
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\s\?\s|=|<<|<<=|%=|&=|\*=|\*\*=|\+=|\-=|\^=|\|{1,2}=|<<|<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|%|&|\*\*|\*|\+|\-|\/|\||~|>>/g
+ },
+ {
+ matches: {
+ 1: 'keyword.operator.logical'
+ },
+ pattern: /[^\.]\b(and|not|or)\b/g
+ },
+
+ /**
+ * Functions
+ * 1. No support for marking function parameters
+ */
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(def)\s(.*?)(?=(\s|\())/g
+ }
+ ],
+ sql: [
+ {
+ matches: {
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"|`){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=|:|\+|\.|\{|,)(('|"|`)([^\\\1]|\\.)*?(\3))/gm
+ },
+ {
+ name: 'comment',
+ pattern: /--.*$|\/\*[\s\S]*?\*\/|(\/\/)[\s\S]*?$/gm
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi
+ },
+ {
+ name: 'function.call',
+ pattern: /(\w+?)(?=\()/g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(ABSOLUTE|ACTION|ADA|ADD|ALL|ALLOCATE|ALTER|AND|ANY|ARE|AS|ASC|ASSERTION|AT|AUTHORIZATION|AVG|BEGIN|BETWEEN|BIT|BIT_LENGTH|BOTH|BY|CASCADE|CASCADED|CASE|CAST|CATALOG|CHAR|CHARACTER|CHARACTER_LENGTH|CHAR_LENGTH|CHECK|CLOSE|COALESCE|COLLATE|COLLATION|COLUMN|COMMIT|CONNECT|CONNECTION|CONSTRAINT|CONSTRAINTS|CONTINUE|CONVERT|CORRESPONDING|COUNT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATE|DAY|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFERRABLE|DEFERRED|DELETE|DESC|DESCRIBE|DESCRIPTOR|DIAGNOSTICS|DISCONNECT|DISTINCT|DOMAIN|DOUBLE|DROP|ELSE|END|END-EXEC|ESCAPE|EXCEPT|EXCEPTION|EXEC|EXECUTE|EXISTS|EXTERNAL|EXTRACT|FALSE|FETCH|FIRST|FLOAT|FOR|FOREIGN|FORTRAN|FOUND|FROM|FULL|GET|GLOBAL|GO|GOTO|GRANT|GROUP|HAVING|HOUR|IDENTITY|IMMEDIATE|IN|INCLUDE|INDEX|INDICATOR|INITIALLY|INNER|INPUT|INSENSITIVE|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|IS|ISOLATION|JOIN|KEY|LANGUAGE|LAST|LEADING|LEFT|LEVEL|LIKE|LIMIT|LOCAL|LOWER|MATCH|MAX|MIN|MINUTE|MODULE|MONTH|NAMES|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONE|NOT|NULL|NULLIF|NUMERIC|OCTET_LENGTH|OF|ON|ONLY|OPEN|OPTION|OR|ORDER|OUTER|OUTPUT|OVERLAPS|PAD|PARTIAL|PASCAL|POSITION|PRECISION|PREPARE|PRESERVE|PRIMARY|PRIOR|PRIVILEGES|PROCEDURE|PUBLIC|READ|REAL|REFERENCES|RELATIVE|RESTRICT|REVOKE|RIGHT|ROLLBACK|ROWS|SCHEMA|SCROLL|SECOND|SECTION|SELECT|SESSION|SESSION_USER|SET|SIZE|SMALLINT|SOME|SPACE|SQL|SQLCA|SQLCODE|SQLERROR|SQLSTATE|SQLWARNING|SUBSTRING|SUM|SYSTEM_USER|TABLE|TEMPORARY|THEN|TIME|TIMESTAMP|TIMEZONE_HOUR|TIMEZONE_MINUTE|TO|TRAILING|TRANSACTION|TRANSLATE|TRANSLATION|TRIM|TRUE|UNION|UNIQUE|UNKNOWN|UPDATE|UPPER|USAGE|USER|USING|VALUE|VALUES|VARCHAR|VARYING|VIEW|WHEN|WHENEVER|WHERE|WITH|WORK|WRITE|YEAR|ZONE|USE)(?=\b)/gi
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\+|\!|\-|&(gt|lt|amp);|\||\*|=/g
+ }
+ ],
+ scheme: [
+ {
+ /* making peace with HTML */
+ name: 'plain',
+ pattern: />|</g
+ },
+ {
+ name: 'comment',
+ pattern: /;.*$/gm
+ },
+ {
+ name: 'constant.language',
+ pattern: /#t|#f|'\(\)/g
+ },
+ {
+ name: 'constant.symbol',
+ pattern: /'[^()\s#]+/g
+ },
+ {
+ name: 'constant.number',
+ pattern: /\b\d+(?:\.\d*)?\b/g
+ },
+ {
+ name: 'string',
+ pattern: /".+?"/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'variable'
+ },
+ pattern: /\(\s*(define)\s+\(?(\S+)/g
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\(\s*(begin|define\-syntax|if|lambda|quasiquote|quote|set!|syntax\-rules|and|and\-let\*|case|cond|delay|do|else|or|let|let\*|let\-syntax|letrec|letrec\-syntax)(?=[\]()\s#])/g
+ },
+ {
+ matches: {
+ 1: 'entity.function'
+ },
+ pattern: /\(\s*(eqv\?|eq\?|equal\?|number\?|complex\?|real\?|rational\?|integer\?|exact\?|inexact\?|=|<|>|<=|>=|zero\?|positive\?|negative\?|odd\?|even\?|max|min|\+|\-|\*|\/|abs|quotient|remainder|modulo|gcd|lcm|numerator|denominator|floor|ceiling|truncate|round|rationalize|exp|log|sin|cos|tan|asin|acos|atan|sqrt|expt|make\-rectangular|make\-polar|real\-part|imag\-part|magnitude|angle|exact\->inexact|inexact\->exact|number\->string|string\->number|not|boolean\?|pair\?|cons|car|cdr|set\-car!|set\-cdr!|caar|cadr|cdar|cddr|caaar|caadr|cadar|caddr|cdaar|cdadr|cddar|cdddr|caaaar|caaadr|caadar|caaddr|cadaar|cadadr|caddar|cadddr|cdaaar|cdaadr|cdadar|cdaddr|cddaar|cddadr|cdddar|cddddr|null\?|list\?|list|length|append|reverse|list\-tail|list\-ref|memq|memv|member|assq|assv|assoc|symbol\?|symbol\->string|string\->symbol|char\?|char=\?|char<\?|char>\?|char<=\?|char>=\?|char\-ci=\?|char\-ci<\?|char\-ci>\?|char\-ci<=\?|char\-ci>=\?|char\-alphabetic\?|char\-numeric\?|char\-whitespace\?|char\-upper\-case\?|char\-lower\-case\?|char\->integer|integer\->char|char\-upcase|char\-downcase|string\?|make\-string|string|string\-length|string\-ref|string\-set!|string=\?|string\-ci=\?|string<\?|string>\?|string<=\?|string>=\?|string\-ci<\?|string\-ci>\?|string\-ci<=\?|string\-ci>=\?|substring|string\-append|string\->list|list\->string|string\-copy|string\-fill!|vector\?|make\-vector|vector|vector\-length|vector\-ref|vector\-set!|vector\->list|list\->vector|vector\-fill!|procedure\?|apply|map|for\-each|force|call\-with\-current\-continuation|call\/cc|values|call\-with\-values|dynamic\-wind|eval|scheme\-report\-environment|null\-environment|interaction\-environment|call\-with\-input\-file|call\-with\-output\-file|input\-port\?|output\-port\?|current\-input\-port|current\-output\-port|with\-input\-from\-file|with\-output\-to\-file|open\-input\-file|open\-output\-file|close\-input\-port|close\-output\-port|read|read\-char|peek\-char|eof\-object\?|char\-ready\?|write|display|newline|write\-char|load|transcript\-on|transcript\-off)(?=[\]()\s#])/g
+ }
+ ],
+ r: [
+ /**
+ * Note that a valid variable name is of the form:
+ * [.a-zA-Z][0-9a-zA-Z._]*
+ */
+ {
+ matches: {
+ 1: {
+ name: 'keyword.operator',
+ pattern: /\=|<\-|<-/g
+ },
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=|:)(('|")([^\\\1]|\\.)*?(\3))/gm
+ },
+
+ /**
+ * Most of these are known via the Language Reference.
+ * The built-in constant symbols are known via ?Constants.
+ */
+ {
+ matches: {
+ 1: 'constant.language'
+ },
+ pattern: /\b(NULL|NA|TRUE|FALSE|T|F|NaN|Inf|NA_integer_|NA_real_|NA_complex_|NA_character_)\b/g
+ },
+ {
+ matches: {
+ 1: 'constant.symbol'
+ },
+ pattern: /[^0-9a-zA-Z\._](LETTERS|letters|month\.(abb|name)|pi)/g
+ },
+
+ /**
+ * @todo: The list subsetting operator isn't quite working properly.
+ * It includes the previous variable when it should only match [[
+ */
+ {
+ name: 'keyword.operator',
+ pattern: /<-|<-|-|==|<=|<=|>>|>=|<|>|&&|&&|&|&|!=|\|\|?|\*|\+|\^|\/|%%|%\/%|\=|%in%|%\*%|%o%|%x%|\$|:|~|\[{1,2}|\]{1,2}/g
+ },
+ {
+ matches: {
+ 1: 'storage',
+ 3: 'entity.function'
+ },
+ pattern: /(\s|^)(.*)(?=\s?=\s?function\s\()/g
+ },
+ {
+ matches: {
+ 1: 'storage.function'
+ },
+ pattern: /[^a-zA-Z0-9._](function)(?=\s*\()/g
+ },
+ {
+ matches: {
+ 1: 'namespace',
+ 2: 'keyword.operator',
+ 3: 'function.call'
+ },
+ pattern: /([a-zA-Z][a-zA-Z0-9._]+)([:]{2,3})([.a-zA-Z][a-zA-Z0-9._]*(?=\s*\())\b/g
+ },
+
+ /*
+ * Note that we would perhaps match more builtin functions and
+ * variables, but there are so many that most are ommitted for now.
+ * See ?builtins for more info.
+ *
+ * @todo: Fix the case where we have a function like tmp.logical().
+ * This should just be a function call, at the moment it's
+ * only partly a function all.
+ */
+ {
+ name: 'support.function',
+ pattern: /(^|[^0-9a-zA-Z\._])(array|character|complex|data\.frame|double|integer|list|logical|matrix|numeric|vector)(?=\s*\()/g
+ }
+ ],
+ haskell: [
+ ///- Comments
+ {
+ name: 'comment',
+ pattern: /\{\-\-[\s\S(\w+)]+[\-\-][\}$]/gm
+ // /\{\-{2}[\s\S(.*)]+[\-\-][\}$]/gm [multiple lines]
+ },
+ {
+ name: 'comment',
+ pattern: /\-\-(.*)/g
+ // /\-\-\s(.+)$/gm [single]
+ },
+ ///- End Comments
+
+ ///- Namespace (module)
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'support.namespace'
+ },
+ pattern: /\b(module)\s(\w+)\s[\(]?(\w+)?[\)?]\swhere/g
+ },
+ ///- End Namespace (module)
+
+ ///- Keywords and Operators
+ {
+ name: 'keyword.operator',
+ pattern: /\+|\!|\-|&(gt|lt|amp);|\/\=|\||\@|\:|\.|\+{2}|\:|\*|\=|#|\.{2}|(\\)[a-zA-Z_]/g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(case|class|foreign|hiding|qualified|data|family|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|in|otherwise|module|newtype|of|then|type|where)\b/g
+ },
+ {
+ name: 'keyword',
+ pattern: /[\`][a-zA-Z_']*?[\`]/g
+ },
+ ///- End Keywords and Operators
+
+
+ ///- Infix|Infixr|Infixl
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'keyword.operator'
+ },
+ pattern: /\b(infix|infixr|infixl)+\s\d+\s(\w+)*/g
+ },
+ ///- End Infix|Infixr|Infixl
+
+ {
+ name: 'entity.class',
+ pattern: /\b([A-Z][A-Za-z0-9_']*)/g
+ },
+
+ // From c.js
+ {
+ name: 'meta.preprocessor',
+ matches: {
+ 1: [
+ {
+ matches: {
+ 1: 'keyword.define',
+ 2: 'entity.name'
+ },
+ pattern: /(\w+)\s(\w+)\b/g
+ },
+ {
+ name: 'keyword.define',
+ pattern: /endif/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\d+/g
+ },
+ {
+ matches: {
+ 1: 'keyword.include',
+ 2: 'string'
+ },
+ pattern: /(include)\s(.*?)$/g
+ }
+ ]
+ },
+ pattern: /^\#([\S\s]*?)$/gm
+ }
+ ],
+ d: [
+ {
+ name: 'constant',
+ pattern: /\b(false|null|true)\b/gm
+ },
+ {
+ // http://dlang.org/lex.html
+ name: 'keyword',
+ pattern: /\b(abstract|alias|align|asm|assert|auto|body|bool|break|byte|case|cast|catch|cdouble|cent|cfloat|char|class|const|continue|creal|dchar|debug|default|delegate|delete|deprecated|do|double|else|enum|export|extern|final|finally|float|for|foreach|foreach_reverse|function|goto|idouble|if|ifloat|immutable|import|in|inout|int|interface|invariant|ireal|is|lazy|long|macro|mixin|module|new|nothrow|null|out|override|package|pragma|private|protected|public|pure|real|ref|return|scope|shared|short|size_t|static|string|struct|super|switch|synchronized|template|this|throw|try|typedef|typeid|typeof|ubyte|ucent|uint|ulong|union|unittest|ushort|version|void|volatile|wchar|while|with|__FILE__|__LINE__|__gshared|__traits|__vector|__parameters)\b/gm
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/gm
+ }
+ },
+ pattern: /(typeof)\s([^\$].*?)(\)|;)/gm
+ },
+ {
+ matches: {
+ 1: 'keyword.namespace',
+ 2: {
+ name: 'support.namespace',
+ pattern: /\w+/gm
+ }
+ },
+ pattern: /\b(namespace)\s(.*?);/gm
+ },
+ {
+ matches: {
+ 1: 'storage.modifier',
+ 2: 'storage.class',
+ 3: 'entity.name.class',
+ 4: 'storage.modifier.extends',
+ 5: 'entity.other.inherited-class'
+ },
+ pattern: /\b(abstract|sealed)?\s?(class)\s(\w+)(\sextends\s)?([\w\\]*)?\s?\{?(\n|\})/gm
+ },
+ {
+ name: 'keyword.static',
+ pattern: /\b(static)\b/gm
+ },
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/gm
+ }
+
+ },
+ pattern: /\b(new)\s([^\$].*?)(?=\)|\(|;|&)/gm
+ },
+ {
+ name: 'string',
+ pattern: /("|')(.*?)\1/gm
+ },
+ {
+ name: 'integer',
+ pattern: /\b(0x[\da-f]+|\d+)\b/gm
+ },
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\/|\/\+[\s\S]*?\+\/|(\/\/)[\s\S]*?$/gm
+ },
+ {
+ // http://dlang.org/operatoroverloading.html
+ name: 'operator',
+ // / /= &= && & |= || | -= -- - += ++ + <= << < <<= <>= <> > >>>= >>= >= >> >>> != !<>= !<> !<= !< !>= !> ! [ ] $ == = *= * %= % ^^= ^= ^^ ^ ~= ~ @ => :
+ pattern: /(\/|\/=|&=|&&|&|\|=|\|\|\||\-=|\-\-|\-|\+=|\+\+|\+|<=|<<|<|<<=|<>=|<>|>|>>>=|>>=|>=|>>|>>>|!=|!<>=|!<>|!<=|!<|!>=|!>|!|[|]|\$|==|=|\*=|\*|%=|%|\^\^=|\^=|\^\^|\^|~=|~|@|=>|\:)/gm
+ }
+ ],
+ smalltalk: [
+ {
+ name: 'keyword.pseudovariable',
+ pattern: /self|thisContext/g
+ },
+ {
+ name: 'keyword.constant',
+ pattern: /false|nil|true/g
+ },
+ {
+ name: 'string',
+ pattern: /'([^']|'')*'/g
+ },
+ {
+ name: 'string.symbol',
+ pattern: /#\w+|#'([^']|'')*'/g
+ },
+ {
+ name: 'string.character',
+ pattern: /\$\w+/g
+ },
+ {
+ name: 'comment',
+ pattern: /"([^"]|"")*"/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /-?\d+(\.\d+)?((r-?|s)[A-Za-z0-9]+|e-?[0-9]+)?/g
+ },
+ {
+ name: 'entity.name.class',
+ pattern: /\b[A-Z]\w*/g
+ },
+ {
+ name: 'entity.name.function',
+ pattern: /\b[a-z]\w*:?/g
+ },
+ {
+ name: 'entity.name.binary',
+ pattern: /(<|>|&|[=~\|\\\/!@*\-_+])+/g
+ },
+ {
+ name: 'operator.delimiter',
+ pattern: /;[\(\)\[\]\{\}]|#\[|#\(^\./g
+ }
+ ],
+ oz : [
+ // https://github.com/mozart/vscode-oz/blob/master/syntaxes/oz.tmLanguage.json
+ // TODO add missing css
+ {
+ name: "operator",
+ pattern: /(<:|:>|::|&|@|#|_|\[\]|\.\.\.)/g
+ },
+ {
+ name: "operator.assignment",
+ pattern: /(\=|\:=)/g
+ },
+ {
+ name: "operator.comparison",
+ pattern: /<|=<|==|\=|>=|>/g
+ },
+ {
+ name: "operator.list",
+ pattern: /\b\|\b/g
+ },
+ {
+ name: "constant.numeric",
+ pattern: /(\d+\.\d+|\d+)/g
+ },
+ {
+ name: "constant.language",
+ pattern: /\b(false|true|nil)\b/g
+ },
+ {
+ name: "variable",
+ pattern: /[A-Z][0-9A-z]*/g
+ },
+ {
+ name: "keyword.control",
+ pattern: /(? b - a);
}
-/**
- * Encodes < and > as html entities
- *
- * @param {string} code
- * @return {string}
- */
-function htmlEntities(code) {
- return code.replace(//g, '>').replace(/&(?![\w\#]+;)/g, '&');
-}
-
/**
* Determines if two different matches have complete overlap with each other
*
@@ -250,6 +240,7 @@ export class Prism {
regex = _cloneRegex(regex);
const match = regex.exec(code);
+
if (!match) {
return false;
}
@@ -439,4 +430,4 @@ export class Prism {
this.refract = _processCodeWithPatterns;
}
-}
\ No newline at end of file
+}
diff --git a/src/publics/js/dev/page/editor/tab.js b/src/publics/js/dev/page/editor/tab.js
index 47719a4..249a1c0 100644
--- a/src/publics/js/dev/page/editor/tab.js
+++ b/src/publics/js/dev/page/editor/tab.js
@@ -2,8 +2,8 @@
* This module deals with tabs.
* @author Brieuc Dubois
* @date Created on 15/11/2020
- * @date Last modification on 15/11/2020
- * @version 1.0.0
+ * @date Last modification on 27/11/2020
+ * @version 1.1.0
*/
@@ -26,6 +26,7 @@ export default class Tab{
*/
constructor(element, type=TabType.SPACES, size=null) {
this.element = element;
+ this.oldSize = size || 4;
this.set(type, size);
console.log(this);
}
@@ -38,7 +39,6 @@ export default class Tab{
set(type, size=null){
this.type = type;
this.setSize(size);
- console.log(this);
}
/**
@@ -46,6 +46,7 @@ export default class Tab{
* @param {number} size
*/
setSize(size){
+ this.oldSize = this.size;
if(this.type === TabType.TAB){
this.size = size;
if(!this.size) this.size = 8;
@@ -53,7 +54,6 @@ export default class Tab{
}else if(this.type === TabType.SPACES){
this.size = size;
if(!this.size) this.size = 4;
- console.log(this.size, size);
this.element.style.tabSize = this.size*2 + 'px';
}else{
this.size = size;
@@ -73,6 +73,7 @@ export default class Tab{
/**
* Return spaces based on position
* @param {number} position
+ * @return {string}
*/
getCompletion(position){
if(this.type === TabType.SPACES) return ' '.repeat(this.size-position%this.size);
@@ -82,9 +83,21 @@ export default class Tab{
/**
* Return spaces based on position
* @param {number} position
+ * @return {number}
*/
getCompletionSize(position){
if(this.type === TabType.SPACES) return this.size-position%this.size;
return 1;
}
+
+ /**
+ * Update text based on oldSize
+ * @param {string} text
+ * @return {string}
+ */
+ updateText(text){
+ const current = Math.max(text.search(/\S/), 0);
+ const amount = ~~(current/this.oldSize) * this.size + current%this.oldSize;
+ return ' '.repeat(amount) + text.slice(current)
+ }
}
diff --git a/src/routes/index.js b/src/routes/index.js
index da1c297..6a26f09 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -22,6 +22,7 @@ const express = require('express');
* @type {object}
*/
const db = require('../db/MongoDB');
+const languages = require('../config/langages');
const config = require('../config/config');
/**
* Express router.
@@ -53,7 +54,9 @@ router.get('/', (req, res) => {
router.post('/create_document', async (req, res, next) => {
try {
//const language = req.body.language
- let documentId = await db.createDocument('python');
+ // if (langages.includes(langage))
+ const language = 'python';
+ let documentId = await db.createDocument(language);
if (documentId) {
res.redirect(`/editor/${documentId}`);
}
diff --git a/src/socket/socket.js b/src/socket/socket.js
index 8ae3ac0..4839098 100644
--- a/src/socket/socket.js
+++ b/src/socket/socket.js
@@ -8,6 +8,7 @@
*/
const discordWebhook = require('webhook-discord');
const debug = require('debug');
+const languages = require('../config/langages');
const config = require('../config/config');
const prom = require('./prom');
@@ -25,6 +26,8 @@ const rooms = {};
const hook = config.DISCORD_WEBHOOK ? new discordWebhook.Webhook(config.DISCORD_WEBHOOK) : null;
+
+
module.exports = function (wss) {
// Based on https://stackoverflow.com/a/62867363
wss.on('connection', socket => {
@@ -86,8 +89,11 @@ module.exports = function (wss) {
case 'language':
try {
- broadcastRoomExceptSender(data, 'language', data.language);
- const success = db.changeLanguage(data.room, data.language);
+ let success = false;
+ if (languages.includes(data.data.language)) {
+ broadcastRoomExceptSender(data, 'uuid', data.uuid);
+ success = db.changeLanguage(data.room, data.data.language);
+ }
if (!success) socket.send(JSON.stringify({event: 'language', success: false}));
} catch (err) {
if (config.DEBUG) {
@@ -97,8 +103,12 @@ module.exports = function (wss) {
break;
case 'changeTabSize':
try {
- broadcastRoomExceptSender(data, 'tabSize', data.tabSize);
- const success = db.changeTabSize(data.room, data.tabSize);
+ let success = false;
+ data.data.size = parseInt(data.data.size);
+ if (Number.isInteger(data.data.size)) {
+ broadcastRoomExceptSender(data, 'uuid', data.uuid);
+ success = db.changeTabSize(data.room, data.data.size);
+ }
if (!success) socket.send(JSON.stringify({event: 'changeTabSize', success: false}));
} catch (err) {
if (config.DEBUG) {
diff --git a/src/views/editor.html b/src/views/editor.html
index e4809f9..5850d9e 100644
--- a/src/views/editor.html
+++ b/src/views/editor.html
@@ -8,7 +8,7 @@
{% endblock %}
{% block header %}
- CODEWE - {{ document['document_id'] }}
+ CODEWE - {{ document['document_id'] }}
@@ -20,15 +20,47 @@ CODE{{ line['content'] }}
{% endfor %}
+
{% endblock %}
{% block scripts %}
{% if production %}
{% else %}
{% endif %}
+
+
{% endblock %}